About me
home
Portfolio
home
🏫

3 Custom FIWARE 실습

fiware-for-time-series-data
taeyoungYoo
서버 구축하는 방법
1.
git clone https://github.com/taeyoungYoo/fiware-for-time-series-data.git 터미널에 입력하여 다운로드 받고 해당 디렉토리 들어가기
2.
chmod +x services_esc 해주기
3.
vim services_esc 로 들어가서 docker-compose를 docker compose 로 바꾸기
4.
./services_esc create 입력하기
5.
ifconfig로 ip 확인하기
enp4s0 에 나오는 inet이 내 ip 이다(172.16.63.209). 밑에 명령어들도 이 ip로 수정하기
라즈베리파이 시작하는 방법
2.
라즈베리파이4 sd카드에 굽기 (SD Card Formatter, balenaEtcher 사용함)

기본 설정 진행

1.
Service 파일
Orion Context Broker LD
IoT Agent UltraLight 2.0
MongoDB
QuantumLeap
redis db
crate db
ld-context(where @context exists)
grafana
2.
포트 정보
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
# Project name COMPOSE_PROJECT_NAME=fiware # Orion variables ORION_LD_PORT=1026 ORION_LD_VERSION=0.8.2 # MongoDB variables MONGO_DB_PORT=27017 MONGO_DB_VERSION=4.4 # IoT Agent Ultralight Variables ULTRALIGHT_VERSION=1.19.0-distroless IOTA_NORTH_PORT=4041 IOTA_SOUTH_PORT=7896 # QuantumLeap Variables QUANTUMLEAP_VERSION=0.8.2 QUANTUMLEAP_PORT=8668 # CrateDB Version CRATE_VERSION=4.1.4 # RedisDB Version REDIS_PORT=6379 REDIS_VERSION=6
JavaScript
복사
service 파일을 실행하고 docker가 성공적으로 실행되면 displayServicies () 에서 자동적으로 docker process를 띄워준다.
정상적으로 아래와 같이 나오는지 확인하자
NAMES STATUS PORTS
fiware-quantumleap Up 11 hours (healthy) 0.0.0.0:8668->8668/tcp fiware-iot-agent Up 11 hours (healthy) 0.0.0.0:4041->4041/tcp, 0.0.0.0:7896->7896/tcp, 4061/tcp fiware-orion Up 11 hours (healthy) 0.0.0.0:1026->1026/tcp fiware-ld-context Up 11 hours (healthy) 0.0.0.0:3004->80/tcp
db-crate Up 11 hours 0.0.0.0:4200->4200/tcp, 0.0.0.0:4300->4300/tcp, 5432/tcp db-redis Up 11 hours (healthy) 0.0.0.0:6379->6379/tcp db-mongo Up 11 hours (healthy) 0.0.0.0:27017->27017/tcp
grafana Up 11 hours 0.0.0.0:3003->3000/tcp
김영준 정상적으로 출력완료
Windows로 실행중이라면 docker 실행창이 이렇게 나와야한다.

Provisioning service

현재 목표로 하는 시스템은 acoustic sensor가 측정한 데이터를 판별한 결과를 받아 처리하는 시스템이다. 이에 앞서 지금까지 tutorial에서 진행한 데이터를 바탕으로 먼저 정상 동작하는지 확인해보자.
fiware 서버는 local에 구축하였고 raspberry pi에서 신호를 보낸다.
<Local 서버에 프로비져닝> curl -iX POST 'http://localhost:4041/iot/services' \ -H 'fiware-service: openiot' \ -H 'fiware-servicepath: /' \ -H 'Content-Type: application/json' \ --data-raw '{ "services": [ { "apikey": "rtestaeyoungtest0530", "cbroker": "http://orion:1026", "entity_type": "Device", "timezone": "Asia/Seoul", "resource": "/iot/d", "attributes": [ { "object_id": "t", "type": "Integer", "name": "temperature", "metadata": { "unitCode": {"type": "Property", "value": "CEL" }} }, { "object_id": "s", "name": "status", "type": "Property" }, { "object_id": "gps", "name": "location", "type": "geo:point" } ], "static_attributes": [ { "name": "category", "type": "Property", "value": "sensor" }, { "name": "supportedProtocol", "type": "Property", "value": "ul20" } ] } ] }'
JavaScript
복사
정상적으로 생성되었다면 아래와 같은 문구가 나온다.
HTTP/1.1 201 Created X-Powered-By: Express Fiware-Correlator: 79f728ce-0a2b-4441-a6ff-8b67743d839a Content-Type: application/json; charset=utf-8 Content-Length: 2 ETag: W/"2-vyGp6PvFo4RvsFtPoIWeCReyIC8" Date: Mon, 30 May 2022 08:09:49 GMT Connection: keep-alive Keep-Alive: timeout=5
JavaScript
복사
서비스가 잘 입력되었는지 다시 확인하고 싶다면 전체 서비스 그룹을 출력해보자.
curl -X GET \ 'http://localhost:4041/iot/services' \ -H 'fiware-service: openiot' \ -H 'fiware-servicepath: /' | python -m json.tool
JavaScript
복사
아래와 같은 결과가 나온다.
{ "count": 1, "services": [ { "commands": [], "lazy": [], "attributes": [ { "object_id": "t", "type": "Integer", "name": "temperature", "metadata": { "unitCode": { "type": "Property", "value": "CEL" } } }, { "object_id": "s", "name": "status", "type": "Property" }, { "object_id": "gps", "name": "location", "type": "geo:point" } ], "_id": "62947bcddb4e283cef5ed692", "resource": "/iot/d", "apikey": "rtestaeyoungtest0530", "service": "openiot", "subservice": "/", "timezone": "Asia/Seoul", "__v": 0, "static_attributes": [ { "name": "category", "type": "Property", "value": "sensor" }, { "name": "supportedProtocol", "type": "Property", "value": "ul20" } ], "internal_attributes": [], "entity_type": "Device" } ] }
JavaScript
복사
서비스 그룹을 등록했으니 이제 device(sensor) 정보를 등록하자.
Raspberry Pi에서 정보를 보내자. 이때 localhost 자리에 대신 local 서버의 ip 주소를 적어준다.
만약 WSL을 사용하는 경우 ifconfig에서 나오는 IP주소는 로컬에서 이더넷 어댑터를 통해 연결된 결과기에 그 값도 다르고 default로 외부에서 접속을 할 수 없다.
<Raspberry Pi> 에서 전송 ######## ip 주소 바꾸기 ###### curl -L -X POST 'http://172.16.63.209:4041/iot/devices' \ -H 'fiware-service: openiot' \ -H 'fiware-servicepath: /' \ -H 'Content-Type: application/json' \ --data-raw '{ "devices": [ { "device_id": "temperature002", "entity_name": "urn:ngsi-ld:Device:temperature002", "entity_type": "Device", "timezone": "Asia/Seoul", "attributes": [ { "object_id": "t", "name": "temperature", "type": "Property", "metadata": { "unitCode": { "type": "Text", "value": "CEL" } } } ], "static_attributes": [ {"name": "description", "type":"Property", "value": "Temperature Sensor"}, {"name": "category", "type":"Property", "value": ["sensor"]}, {"name": "controlledProperty", "type": "Property", "value": "temperature"}, {"name": "supportedProtocol", "type": "Property", "value": ["ul20"]} ] } ] }'
JavaScript
복사
Sensor를 등록해주자. sensor의 device_id는 temperature002이다.
이때 자신만의 센서를 만들겠다고 fiware-service, fiware-servicepath 헤더를 변경하려고 하는 경우 적용이 안된다. 그 이유는 앞서 서비스 프로비져닝을 할 때 fiware-service, fiware-servicepath를 각각 openiot, / 로 정했기 때문이다.
물론 뒤에서 진행하겠지만 여기서부터 자신만의 헤더를 정의하고 싶다면(ex. fiware-service header as youngCustomDevice, fiware-servicepath header as /jungnanggu) 앞에서 서비스 프로비져닝을 진행한 지점부터 다시 선언하자.
이 경우 깔끔하게 진행하기를 원한다면 아래 코드로 서비스를 삭제하고 다시 진행하자
curl -iX DELETE \ 'http://localhost:4041/iot/services/?resource=/iot/d&apikey=rtestaeyoungtest0530' \ -H 'fiware-service: openiot' \ -H 'fiware-servicepath: /'
JavaScript
복사
여기까지 마쳤다면 이제 raspberry pi에 연결된 센서가 값이 변경되어 이를 업데이트하는 상황을 생각해보자. 업데이트된 값을 파이에서 보내고 로컬 fiware 서버에서 확인해보자.
curl -L -X POST 'http://172.16.63.209:7896/iot/d?k=rtestaeyoungtest0530&i=temperature002' \ -H 'Content-Type: text/plain' \ --data-raw 't|200'
JavaScript
복사
위 명령어는 파이에서 보낸 명령어다. 이제 로컬에서 확인하자.
curl -G -iX GET 'http://localhost:1026/ngsi-ld/v1/entities/urn:ngsi-ld:Device:temperature002' \ -H 'fiware-service: openiot' \ -H 'fiware-servicepath: /' \ -H 'Link: <http://context/ngsi-context.jsonld>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json"' \ -d 'attrs=temperature'
JavaScript
복사
출력된 결과를 보면 "temperature":{"value":"200","type":"Property","unitCode":"CEL","observedAt":"2022-05-30T10:39:04.875Z"} 부분이 있을 것이다. value가 우리가 입력한 200으로 변경되어있다.
이때 observedAt은 가장 최근에 변경된 시간을 의미한다. 시간은 Zulu timezone 기준이기에 우리 시간보다 9시간 늦을 것이다.
이렇게 지금까지 배운 FIWARE 기초를 통해 서비스를 프로비져닝하고 센서를 등록하고 데이터를 업데이트까지 해봤다.
이제 우리가 목표하는 acoustic sensor를 가정해서 진행해보자.

Provisioning my own service

목표하는 acoustic sensor case 적용 서비스를 만들자.
먼저 로컬 서비스를 provisioning해준다.
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": "rtestaeyoungtest0710", "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
복사
먼저 기존과 다른 점은 헤더부분이다(fiware-service, fiware-servicepath). 기존 openiot에서 youngCustomDevice, ‘/’에서 ‘/escTest’로 변경되었다.
두 번째는 사용하는 sensor다. 우리는 이제 온도 센서가 아닌 acoustic sensor에서 10개의 class 분포를 받음을 목표로 한다.
정상적으로 실행 시 아래와 같은 결과가 나오게 된다.
HTTP/1.1 201 Created X-Powered-By: Express Fiware-Correlator: ff62a3dc-42e6-4506-97f3-a653b1376bd0 Content-Type: application/json; charset=utf-8 Content-Length: 2 ETag: W/"2-vyGp6PvFo4RvsFtPoIWeCReyIC8" Date: Sun, 10 Jul 2022 05:03:44 GMT Connection: keep-alive Keep-Alive: timeout=5
JavaScript
복사
마찬가지로 전체 서비스를 출력해 정상 등록을 확인한다.
curl -X GET \ 'http://localhost:4041/iot/services' \ -H 'fiware-service: youngCustomDevice' \ -H 'fiware-servicepath: /escTest' | python3 -m json.tool
JavaScript
복사
여기서도 헤더파일에 주의하자.
결과는 아래와 같다.
{ "count": 1, "services": [ { "commands": [], "lazy": [], "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" } ], "_id": "62ca5db0fc8263c7109ec3a8", "resource": "/iot/d", "apikey": "rtestaeyoungtest0710", "service": "youngcustomdevice", "subservice": "/escTest", "timezone": "Asia/Seoul", "__v": 0, "static_attributes": [ { "name": "category", "type": "Property", "value": "sensor" }, { "name": "supportedProtocol", "type": "Property", "value": "ul20" } ], "internal_attributes": [], "entity_type": "Device" } ] }
JavaScript
복사
이제 device(sensor) 정보를 등록하자. device는 raspberry pi라 가정하고 이제 pi에서 명령을 보내자.
####### ip 확인하기 ################## 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
복사
이어서 데이터를 보낸다.
####### ip 확인하기 ################## curl -L -X POST 'http://172.16.63.209:7896/iot/d?k=rtestaeyoungtest0710&i=acoustic01' \ -H 'Content-Type: text/plain' \ --data-raw 'c1|0.12|c2|0.08|c3|0.15|c4|0.05|c5|0.06|c6|0.14|c7|0.19|c8|0.01|c9|0.10|c10|0.10'
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
복사
아래와 같은 결과가 나온다.
{ "@context": "http://context/ngsi-context.jsonld", "id": "urn:ngsi-ld:Device:acoustic01", "type": "Device", "class1": { "type": "Property", "value": 0.12, "observedAt": "2022-07-10T06:05:07.489Z" }, "class10": { "type": "Property", "value": 0.1, "observedAt": "2022-07-10T06:05:07.489Z" }, "class2": { "type": "Property", "value": 0.08, "observedAt": "2022-07-10T06:05:07.489Z" }, "class3": { "type": "Property", "value": 0.15, "observedAt": "2022-07-10T06:05:07.489Z" }, "class4": { "type": "Property", "value": 0.05, "observedAt": "2022-07-10T06:05:07.489Z" }, "class5": { "type": "Property", "value": 0.06, "observedAt": "2022-07-10T06:05:07.489Z" }, "class6": { "type": "Property", "value": 0.14, "observedAt": "2022-07-10T06:05:07.489Z" }, "class7": { "type": "Property", "value": 0.19, "observedAt": "2022-07-10T06:05:07.489Z" }, "class8": { "type": "Property", "value": 0.01, "observedAt": "2022-07-10T06:05:07.489Z" }, "class9": { "type": "Property", "value": 0.1, "observedAt": "2022-07-10T06:05:07.489Z" }, "category": { "type": "Property", "value": "sensor", "observedAt": "2022-07-10T06:05:07.489Z" }, "supportedProtocol": { "type": "Property", "value": "ul20", "observedAt": "2022-07-10T06:05:07.489Z" }, "location": { "type": "GeoProperty", "value": { "type": "Point", "coordinates": [ 0, 0 ] } } }
JavaScript
복사
정상적으로 등록됨을 확인할 수 있다.
여기까지 진행을 통해 로컬 서버에 FIWARE 서버 구축 / 센서단(raspberry Pi 4B 2GB)에서 서버로 데이터 전송 과정을 알아봤다.
정리해보면 FIWARE 서버를 구축하고 정확한 목적(여기서는 acoustic sensor)을 정리하여 서비스를 provisioning하고 provisioning한 서비스에 맞춰 센서에서 정확하게 정보를 전송함이 중요함을 알 수 있다.
지금까지는 모든 request를 curl을 사용해 처리했다. 다음 매뉴얼에서는 python 코드를 활용해 request를 전송하는 과정을 알아본다. 해당 과정을 통해 python을 사용한 데이터 측정 → FIWARE 서버로 데이터 전송 과정을 이룰 수 있다.
해당 과정까지 마친다면 FIWARE 기반 데이터 측정-전송-저장 시스템을 구축한것이다.
이후 남은 과정은 QuantumLeap 등을 통해 historic data를 저장하고 Grafana 등 시각화 툴을 사용해 저장 데이터를 보여주는 부분이다.

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