Mainflux IoT Agent is a communication, execution and SW management agent for Mainflux system.
Get the code:
go get github.com/mainflux/agent
cd $GOPATH/github.com/mainflux/agent
Make:
make
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:
MF_AGENT_BOOTSTRAP_ID=<bootstrap_id> \
MF_AGENT_BOOTSTRAP_KEY=<bootstrap_key> \
MF_AGENT_BOOTSTRAP_URL=http://localhost:9013/things/bootstrap \
build/mainflux-agent
or,if Mainflux UI is used,
MF_AGENT_BOOTSTRAP_ID=<bootstrap_id> \
MF_AGENT_BOOTSTRAP_KEY=<bootstrap_key> \
MF_AGENT_BOOTSTRAP_URL=http://localhost:9013/bootstrap/things/bootstrap \
build/mainflux-agent
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 |
---|---|---|
MF_AGENT_CONFIG_FILE | Location of configuration file | config.toml |
MF_AGENT_LOG_LEVEL | Log level | info |
MF_AGENT_EDGEX_URL | Edgex base url | http://localhost:48090/api/v1/ |
MF_AGENT_MQTT_URL | MQTT broker url | localhost:1883 |
MF_AGENT_HTTP_PORT | Agent http port | 9999 |
MF_AGENT_BOOTSTRAP_URL | Mainflux bootstrap url | http://localhost:9013/things/bootstrap |
MF_AGENT_BOOTSTRAP_ID | Mainflux bootstrap id | |
MF_AGENT_BOOTSTRAP_KEY | Mainflux bootstrap key | |
MF_AGENT_BOOTSTRAP_RETRIES | Number of retries for bootstrap procedure | 5 |
MF_AGENT_BOOTSTRAP_SKIP_TLS | Skip TLS verification for bootstrap | true |
MF_AGENT_BOOTSTRAP_RETRY_DELAY_SECONDS | Number of seconds between retries | 10 |
MF_AGENT_CONTROL_CHANNEL | Channel for sending controls, commands | |
MF_AGENT_DATA_CHANNEL | Channel for data sending | |
MF_AGENT_ENCRYPTION | Encryption | false |
MF_AGENT_BROKER_URL | Broker url | nats://localhost:4222 |
MF_AGENT_MQTT_USERNAME | MQTT username, Mainflux thing id | |
MF_AGENT_MQTT_PASSWORD | MQTT password, Mainflux thing key | |
MF_AGENT_MQTT_SKIP_TLS | Skip TLS verification for MQTT | true |
MF_AGENT_MQTT_MTLS | Use MTLS for MQTT | false |
MF_AGENT_MQTT_CA | Location for CA certificate for MTLS | ca.crt |
MF_AGENT_MQTT_QOS | QoS | 0 |
MF_AGENT_MQTT_RETAIN | MQTT retain | false |
MF_AGENT_MQTT_CLIENT_CERT | Location of client certificate for MTLS | thing.cert |
MF_AGENT_MQTT_CLIENT_PK | Location of client certificate key for MTLS | thing.key |
MF_AGENT_HEARTBEAT_INTERVAL | Interval in which heartbeat from service is expected | 30s |
MF_AGENT_TERMINAL_SESSION_TIMEOUT | Timeout for terminal session | 30s |
Here thing
is a Mainflux 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
).
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\"}]"
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}]"
}
]
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==