Closed c0c0n3 closed 1 year ago
Here's a sum up of how to demo most of what this PR implemented.
First off, build your own KITT4SME cluster in a Multipass VM as explained in the bootstrap procedure. Wait a bit until all services are ready. The commands below use the 192.168.64.20
IP address to reach the Multipass VM; replace 192.168.64.20
in each command with your VM's IP.
Log into Argo CD. There's a ul-agent
app among the platform infra services. Check out all the resources deployed and have a look at the logs. Open the config map, you should be able to see the exact same content as in the config.js
included in this PR.
Provision a service with two devices, one sending data over MQTT and the other over HTTP. Notice it's best to do that in config.js
, but we'll do that manually here to speed things up. So as a rule, there would be no need to expose UL Agent's provisioning API. Since we're bending the rules here, port-forward the agent's provisioning port.
$ kubectl port-forward svc/ulagent 4041:4041
On to the provisioning business. Create a service with an API key of gr33t
, entity type of Greeting
and HTTP endpoint of /iot/d
.
$ curl -iX POST 'http://localhost:4041/iot/services' \
-H 'Content-Type: application/json' \
-H 'fiware-service: greeting' \
-H 'fiware-servicepath: /' \
-d '{
"services": [
{
"apikey": "gr33t",
"entity_type": "Greeting",
"resource": "/iot/d"
}
]
}'
Create two devices to send a greeting message. The message is in the UL format: w|data
, where data
is a greeting the device sends. The corresponding NGSI entity has type Greeting
and a words
attribute holding the actual greeting. The first device has an ID of greeter001
and sends its data over MQTT, whereas the second has ID greeter002
and sends data over HTTP.
$ curl -iX POST \
'http://localhost:4041/iot/devices' \
-H 'Content-Type: application/json' \
-H 'fiware-service: greeting' \
-H 'fiware-servicepath: /' \
-d '{
"devices": [
{
"device_id": "greeter001",
"entity_name": "urn:ngsi-ld:Greeting:001",
"entity_type": "Greeting",
"protocol": "PDI-IoTA-UltraLight",
"transport": "MQTT",
"attributes": [
{ "object_id": "w", "name": "words", "type": "Text" }
]
}
]
}
'
$ curl -iX POST \
'http://localhost:4041/iot/devices' \
-H 'Content-Type: application/json' \
-H 'fiware-service: greeting' \
-H 'fiware-servicepath: /' \
-d '{
"devices": [
{
"device_id": "greeter002",
"entity_name": "urn:ngsi-ld:Greeting:002",
"entity_type": "Greeting",
"protocol": "PDI-IoTA-UltraLight",
"transport": "HTTP",
"attributes": [
{ "object_id": "w", "name": "words", "type": "Text" }
]
}
]
}
'
With this setup, greeter001
is expected to send its UL payload to the MQTT topic
ul/gr33t/greeter001/attrs
whereas greeter002
is supposed to POST its UL payload to the URL
http://192.168.64.20/ulagent/iot/d?k=gr33t&i=greeter002
since our Istio config routes /ulagent/<rest>
to /<rest>
on port 7896
of the ulagent
service.
Finally, check you can retrieve the service and devices you've just created.
$ curl 'http://localhost:4041/iot/services' \
-H 'fiware-service: greeting' \
-H 'fiware-servicepath: /'
{"count":1,"services":[{"apikey":"gr33t","resource":"/iot/d","service":"greeting","subservice":"/","_id":1,"creationDate":1667762295227,"entity_type":"Greeting"}]}
$ curl 'http://localhost:4041/iot/devices' \
-H 'fiware-service: greeting' \
-H 'fiware-servicepath: /'
{"count":2,"devices":[{"device_id":"greeter001","service":"greeting","service_path":"/","entity_name":"urn:ngsi-ld:Greeting:001","entity_type":"Greeting","transport":"MQTT","attributes":[{"object_id":"w","name":"words","type":"Text"}],"commands":[],"static_attributes":[],"protocol":"PDI-IoTA-UltraLight","explicitAttrs":false},{"device_id":"greeter002","service":"greeting","service_path":"/","entity_name":"urn:ngsi-ld:Greeting:002","entity_type":"Greeting","polling":true,"transport":"HTTP","attributes":[{"object_id":"w","name":"words","type":"Text"}],"commands":[],"static_attributes":[],"protocol":"PDI-IoTA-UltraLight","explicitAttrs":false}]}
We're going to use an external WebSocket client to simulate device data coming in over MQTT.
Browse to http://www.emqx.io/online-mqtt-client. Hit the "New Connection" button and enter the following data: name=kitt4sme, client-id=tasty, host=ws://192.168.64.20, path=/mqtt/, port=80, username=iot. You also need to enter the "iot" user's password, which I can't type here obviously. Hit connect, then send the following UL message to the ul/gr33t/greeter001/attrs
topic: w|howzit!
.
Check the "howzit!" greeting trekked all the way to Orion. It should be stored in the "Greeting" entity having an ID of urn:ngsi-ld:Greeting:001
.
$ curl \
'http://192.168.64.20/orion/v2/entities/urn:ngsi-ld:Greeting:001/attrs/words/value' \
-H 'fiware-service: greeting' \
-H 'fiware-servicepath: /'
"howzit!"
Let's also send a greeting from greeter002
. This device sends its data over HTTP
$ curl -iX POST \
'http://192.168.64.20/ulagent/iot/d?k=gr33t&i=greeter002' \
-H 'Content-Type: text/plain' \
-d 'w|ahoy, matey!'
HTTP/1.1 403 Forbidden
date: Sun, 06 Nov 2022 21:17:46 GMT
server: istio-envoy
content-length: 0
What?! Yep, that's right. Our FIWARE OPA policy checks you've got a valid JWT token, since we didn't have one, we got shown the door. How rude. Well, it's too much of a mission to get a token, so let's zap the security policy
$ kubectl -n istio-system delete authorizationpolicy/fiware-opa
and try again
$ curl -iX POST \
'http://192.168.64.20/ulagent/iot/d?k=gr33t&i=greeter002' \
-H 'Content-Type: text/plain' \
-d 'w|ahoy, matey!'
This time the POST goes through and Orion gets our friendly greeting
$ curl \
'http://192.168.64.20/orion/v2/entities/urn:ngsi-ld:Greeting:002/attrs/words/value' \
-H 'fiware-service: greeting' \
-H 'fiware-servicepath: /'
"ahoy, matey!"
As expected, the greeting got stored in the "Greeting" entity having an ID of urn:ngsi-ld:Greeting:002
.
Cool bananas!
This PR implements a fully-fledged UL Agent deployment with HTTP and MQTT transports as #14 requested. Specifically, the following got implemented.
<kitt4sme-base-url>/ulagent/
so devices can POST UL data at<kitt4sme-base-url>/ulagent/iot/d?k=<api-key>&i=<device-id>
. To send UL data over MQTT, devices use the MQTT WebSocket implemented in #181 and the topic:ul/<api-key>/<device-id>/attrs
.config.js
.config.js
in our repo. Look at that file to figure out the lay of the land at a glance. Edit it to add or modify device defs, mappings etc. Argo CD takes care of propagating your changes to the cluster.