Home

Awesome

Mainflux IoT Agent

badge ci release go report card license chat

<p align="center"> <img width="30%" height="30%" src="./docs/img/agent.png"> </p>

Mainflux IoT Agent is a communication, execution and SW management agent for Mainflux system.

Install

Get the code:

go get github.com/mainflux/agent
cd $GOPATH/github.com/mainflux/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:

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

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:

VariableDescriptionDefault
MF_AGENT_CONFIG_FILELocation of configuration fileconfig.toml
MF_AGENT_LOG_LEVELLog levelinfo
MF_AGENT_EDGEX_URLEdgex base urlhttp://localhost:48090/api/v1/
MF_AGENT_MQTT_URLMQTT broker urllocalhost:1883
MF_AGENT_HTTP_PORTAgent http port9999
MF_AGENT_BOOTSTRAP_URLMainflux bootstrap urlhttp://localhost:9013/things/bootstrap
MF_AGENT_BOOTSTRAP_IDMainflux bootstrap id
MF_AGENT_BOOTSTRAP_KEYMainflux bootstrap key
MF_AGENT_BOOTSTRAP_RETRIESNumber of retries for bootstrap procedure5
MF_AGENT_BOOTSTRAP_SKIP_TLSSkip TLS verification for bootstraptrue
MF_AGENT_BOOTSTRAP_RETRY_DELAY_SECONDSNumber of seconds between retries10
MF_AGENT_CONTROL_CHANNELChannel for sending controls, commands
MF_AGENT_DATA_CHANNELChannel for data sending
MF_AGENT_ENCRYPTIONEncryptionfalse
MF_AGENT_BROKER_URLBroker urlnats://localhost:4222
MF_AGENT_MQTT_USERNAMEMQTT username, Mainflux thing id
MF_AGENT_MQTT_PASSWORDMQTT password, Mainflux thing key
MF_AGENT_MQTT_SKIP_TLSSkip TLS verification for MQTTtrue
MF_AGENT_MQTT_MTLSUse MTLS for MQTTfalse
MF_AGENT_MQTT_CALocation for CA certificate for MTLSca.crt
MF_AGENT_MQTT_QOSQoS0
MF_AGENT_MQTT_RETAINMQTT retainfalse
MF_AGENT_MQTT_CLIENT_CERTLocation of client certificate for MTLSthing.cert
MF_AGENT_MQTT_CLIENT_PKLocation of client certificate key for MTLSthing.key
MF_AGENT_HEARTBEAT_INTERVALInterval in which heartbeat from service is expected30s
MF_AGENT_TERMINAL_SESSION_TIMEOUTTimeout for terminal session30s

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).

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:

when messages is received Agent forwards them to Broker on subject:

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>\"}]"

Here is an example how to make payload for the command:

b,_ := toml.Marshal(export.Config)
payload := base64.StdEncoding.EncodeToString(b)

Example payload:

RmlsZSA9ICIuLi9jb25maWdzL2NvbmZpZy50b21sIgoKW2V4cF0KICBsb2dfbGV2ZWwgPSAiZGVidWciCiAgbmF0cyA9ICJuYXRzOi8vMTI3LjAuMC4xOjQyMjIiCiAgcG9ydCA9ICI4MTcwIgoKW21xdHRdCiAgY2FfcGF0aCA9ICJjYS5jcnQiCiAgY2VydF9wYXRoID0gInRoaW5nLmNydCIKICBjaGFubmVsID0gIiIKICBob3N0ID0gInRjcDovL2xvY2FsaG9zdDoxODgzIgogIG10bHMgPSBmYWxzZQogIHBhc3N3b3JkID0gImFjNmI1N2UwLTliNzAtNDVkNi05NGM4LWU2N2FjOTA4NjE2NSIKICBwcml2X2tleV9wYXRoID0gInRoaW5nLmtleSIKICBxb3MgPSAwCiAgcmV0YWluID0gZmFsc2UKICBza2lwX3Rsc192ZXIgPSBmYWxzZQogIHVzZXJuYW1lID0gIjRhNDM3ZjQ2LWRhN2ItNDQ2OS05NmI3LWJlNzU0YjVlOGQzNiIKCltbcm91dGVzXV0KICBtcXR0X3RvcGljID0gIjRjNjZhNzg1LTE5MDAtNDg0NC04Y2FhLTU2ZmI4Y2ZkNjFlYiIKICBuYXRzX3RvcGljID0gIioiCg==

License

Apache-2.0