Awesome
Magistrala IoT Agent
<p align="center"> <img width="30%" height="30%" src="./docs/img/agent.png"> </p>Magistrala IoT Agent is a communication, execution and SW management agent for Magistrala system.
Install
Get the code:
go get github.com/absmach/agent
cd $GOPATH/github.com/absmach/agent
Make:
make
Usage
Get Nats server and start it, by default it starts on port 4222
go install github.com/nats-io/nats-server/v2@latest
nats-server
Create gateway configuration with Provision service or through Mainflux UI.
Start Agent with:
MG_AGENT_BOOTSTRAP_ID=<bootstrap_id> \
MG_AGENT_BOOTSTRAP_KEY=<bootstrap_key> \
MG_AGENT_BOOTSTRAP_URL=http://localhost:9013/things/bootstrap \
build/magistrala-agent
or,if Magistrala UI is used,
MG_AGENT_BOOTSTRAP_ID=<bootstrap_id> \
MG_AGENT_BOOTSTRAP_KEY=<bootstrap_key> \
MG_AGENT_BOOTSTRAP_URL=http://localhost:9013/bootstrap/things/bootstrap \
build/magistrala-agent
Config
Agent configuration is kept in config.toml
if not otherwise specified with env var.
Example configuration:
[Agent]
[Agent.channels]
control = ""
data = ""
[Agent.edgex]
url = "http://localhost:48090/api/v1/"
[Agent.log]
level = "info"
[Agent.mqtt]
ca_path = "ca.crt"
cert_path = "thing.crt"
mtls = false
password = ""
priv_key_path = "thin.key"
qos = 0
retain = false
skip_tls_ver = false
url = "localhost:1883"
username = ""
[Agent.server]
broker_url = "localhost:4222"
port = "9999"
Environment:
Variable | Description | Default |
---|---|---|
MG_AGENT_CONFIG_FILE | Location of configuration file | config.toml |
MG_AGENT_LOG_LEVEL | Log level | info |
MG_AGENT_EDGEX_URL | Edgex base url | http://localhost:48090/api/v1/ |
MG_AGENT_MQTT_URL | MQTT broker url | localhost:1883 |
MG_AGENT_HTTP_PORT | Agent http port | 9999 |
MG_AGENT_BOOTSTRAP_URL | Magistrala bootstrap url | http://localhost:9013/things/bootstrap |
MG_AGENT_BOOTSTRAP_ID | Magistrala bootstrap id | |
MG_AGENT_BOOTSTRAP_KEY | Magistrala bootstrap key | |
MG_AGENT_BOOTSTRAP_RETRIES | Number of retries for bootstrap procedure | 5 |
MG_AGENT_BOOTSTRAP_SKIP_TLS | Skip TLS verification for bootstrap | true |
MG_AGENT_BOOTSTRAP_RETRY_DELAY_SECONDS | Number of seconds between retries | 10 |
MG_AGENT_CONTROL_CHANNEL | Channel for sending controls, commands | |
MG_AGENT_DATA_CHANNEL | Channel for data sending | |
MG_AGENT_ENCRYPTION | Encryption | false |
MG_AGENT_BROKER_URL | Broker url | nats://localhost:4222 |
MG_AGENT_MQTT_USERNAME | MQTT username, Magistrala thing id | |
MG_AGENT_MQTT_PASSWORD | MQTT password, Magistrala thing key | |
MG_AGENT_MQTT_SKIP_TLS | Skip TLS verification for MQTT | true |
MG_AGENT_MQTT_MTLS | Use MTLS for MQTT | false |
MG_AGENT_MQTT_CA | Location for CA certificate for MTLS | ca.crt |
MG_AGENT_MQTT_QOS | QoS | 0 |
MG_AGENT_MQTT_RETAIN | MQTT retain | false |
MG_AGENT_MQTT_CLIENT_CERT | Location of client certificate for MTLS | thing.cert |
MG_AGENT_MQTT_CLIENT_PK | Location of client certificate key for MTLS | thing.key |
MG_AGENT_HEARTBEAT_INTERVAL | Interval in which heartbeat from service is expected | 30s |
MG_AGENT_TERMINAL_SESSION_TIMEOUT | Timeout for terminal session | 30s |
Here thing
is a Magistrala thing, and control channel from channels
is used with req
and res
subtopic
(i.e. app needs to PUB/SUB on /channels/<control_channel_id>/messages/req
and /channels/<control_channel_id>/messages/res
).
Sending commands to other services
You can send commands to other services that are subscribed on the same Broker as Agent.
Commands are being sent via MQTT to topic:
channels/<control_channel_id>/messages/services/<service_name>/<subtopic>
when messages is received Agent forwards them to Broker on subject:
commands.<service_name>.<subtopic>
.
Payload is up to the application and service itself.
Example of on command can be:
mosquitto_pub -u <thing_id> -P <thing_key> -t channels/<control_channel_id>/messages/services/adc -h <mqtt_host> -p 1883 -m "[{\"bn\":\"1:\", \"n\":\"read\", \"vs\":\"temperature\"}]"
Heartbeat service
Services running on the same host can publish to heartbeat.<service-name>.<service-type>
a heartbeat message.
Agent will keep a record on those service and update their live
status.
If heartbeat is not received in 10 sec it marks it offline
.
Upon next heartbeat service will be marked online
again.
To test heartbeat run:
go run -tags <broker_name> ./examples/publish/main.go -s <broker_url> heartbeat.<service-name>.<service-type> "";
Broker names include: nats and rabbitmq.
To check services that are currently registered to agent you can:
curl -s -S X GET http://localhost:9999/services
[
{
"name": "duster",
"last_seen": "2020-04-28T18:06:56.158130519+02:00",
"status": "offline",
"type": "test",
"terminal": 0
},
{
"name": "scrape",
"last_seen": "2020-04-28T18:06:39.58849766+02:00",
"status": "offline",
"type": "test",
"terminal": 0
}
]
Or you can send a command via MQTT to Agent and receive response on MQTT topic like this:
In one terminal subscribe for result:
mosquitto_sub -u <thing_id> -P <thing_key> -t channels/<control_channel_id>/messages/req -h <mqtt_host> -p 1883
In another terminal publish request to view the list of services:
mosquitto_pub -u <thing_id> -P <thing_key> -t channels/<control_channel_id>/messages/req -h <mqtt_host> -p 1883 -m '[{"bn":"1:", "n":"config", "vs":"view"}]'
Check the output in terminal where you subscribed for results. You should see something like:
[
{
"bn": "1",
"n": "view",
"t": 1588091188.8872917,
"vs": "[{\"name\":\"duster\",\"last_seen\":\"2020-04-28T18:06:56.158130519+02:00\",\"status\":\"offline\",\"type\":\"test\",\"terminal\":0},{\"name\":\"scrape\",\"last_seen\":\"2020-04-28T18:06:39.58849766+02:00\",\"status\":\"offline\",\"type\":\"test\",\"terminal\":0}]"
}
]
How to save config via agent
Agent can be used to send configuration file for the Export service from cloud to gateway via MQTT.
Here is the example command:
mosquitto_pub -u <thing_id> -P <thing_key> -t channels/<control_channel_id>/messages/req -h localhost -p 1883 -m "[{\"bn\":\"1:\", \"n\":\"config\", \"vs\":\"<config_file_path>, <file_content_base64>\"}]"
<config_file_path>
- file path where to save contents<file_content_base64>
- file content, base64 encoded marshaled toml.
Here is an example how to make payload for the command:
b,_ := toml.Marshal(export.Config)
payload := base64.StdEncoding.EncodeToString(b)
Example payload:
RmlsZSA9ICIuLi9jb25maWdzL2NvbmZpZy50b21sIgoKW2V4cF0KICBsb2dfbGV2ZWwgPSAiZGVidWciCiAgbmF0cyA9ICJuYXRzOi8vMTI3LjAuMC4xOjQyMjIiCiAgcG9ydCA9ICI4MTcwIgoKW21xdHRdCiAgY2FfcGF0aCA9ICJjYS5jcnQiCiAgY2VydF9wYXRoID0gInRoaW5nLmNydCIKICBjaGFubmVsID0gIiIKICBob3N0ID0gInRjcDovL2xvY2FsaG9zdDoxODgzIgogIG10bHMgPSBmYWxzZQogIHBhc3N3b3JkID0gImFjNmI1N2UwLTliNzAtNDVkNi05NGM4LWU2N2FjOTA4NjE2NSIKICBwcml2X2tleV9wYXRoID0gInRoaW5nLmtleSIKICBxb3MgPSAwCiAgcmV0YWluID0gZmFsc2UKICBza2lwX3Rsc192ZXIgPSBmYWxzZQogIHVzZXJuYW1lID0gIjRhNDM3ZjQ2LWRhN2ItNDQ2OS05NmI3LWJlNzU0YjVlOGQzNiIKCltbcm91dGVzXV0KICBtcXR0X3RvcGljID0gIjRjNjZhNzg1LTE5MDAtNDg0NC04Y2FhLTU2ZmI4Y2ZkNjFlYiIKICBuYXRzX3RvcGljID0gIioiCg==