Manual
do
Maker
.
com
Arregace as mangas, porque esse é um trabalho "daqueles". Precisei fazer um dashboard com Grafana e MQTT. Parecia que tudo seria rápido e tranquilo, considerando meus artigos anteriores sobre Grafana. Bem, não foi nem rápido e nem tranquilo, mas sem dúvidas foi satisfatório. Além do dashboard, fiz a integração com MQTT e alarmes recebidos no Telegram. Bom ou não? Bora começar.
O princípio dessa configuração é seguindo a documentação do projeto Kotori, mas vou descrever o ambiente primeiro.
Pesquisando aqui no blog você encontrará "montes" de tutoriais sobre a utilização de MQTT para diversas plataformas. Se nunca experimentou o MQTT antes, não é por esse artigo que você deve começar.
Também escrevi alguns artigos sobre Grafana com collectd, Grafana com graphite, mas esse é o primeiro tutorial de Grafana e MQTT.
Considerando que queremos fazer telemetria utilizando Grafana e MQTT, devemos configurar nossos dispositivos para enviar dados a um broker. O broker deverá ser próprio, por razões descritas mais adiante. O projeto fiz para gerir Raspberry Pi, por isso se você está procurando uma maneira simples de utilizar MQTT no Raspberry, parabéns, achou!
Além do artigo do parágrafo anterior, vou adicionar a este um script de gerenciamento. Siga com a leitura e não se preocupe com o entendimento agora, apenas visualize que teremos:
Na parte de software teremos:
Ainda no broker, adicionalmente configuraremos um gerente de alarmes; no caso, optei por enviar os alarmes por Telegram, fazendo um bot. Já escrevi sobre bot Telegram nesse artigo.
É um trabalho consideravelmente longo, feito no Ubuntu 20.04 - codinome "focal". Iniciemos.
Vamos começar pelo broker. Siga o tutorial desse artigo para configurar o Mosquitto e depois continue desse parágrafo.
Na parte de instalação não tem muito segredo, o projeto Kotori tem um guia de instalação muito claro. Só que eu usei como "facilitador", depois baixei o pacote .deb mais atual do Grafana e o instalei por cima.
Como vamos usar banco de dados time series entre o Grafana e MQTT, será fundamental ter o horário do servidor devidamente ajustado. Talvez eu tenha exagerado nos processos, mas vamos lá.
#sempre como root. Daqui por diante não vou digitar "sudo bla,bla,bla". Faça assim:
sudo su
timedatectl set-ntp true
Adicionalmente, instalei o ntpdate e fiz a configuração:
apt-get install ntpdate
ntpdate-debian
Se estiver em um servidor remoto e tiver problemas com timezone, configure com o próprio timedatectl. Verifique a saída:
O meu já está configurado, mas com essa saída já identificamos qual a configuração utilizada. Claro que para ver se a hora está certa podemos simplesmente utilizar o comando date. Só que isso não garante a timezone.
Estando errado, liste as timezones para definir a sua. No meu caso, utilizei America/Sao_Paulo.
timedatectl set-timezone your_time_zone
Versões mais antigas do sistema utilizam o tradicional tzdata. Se for seu caso, siga o procedimento abaixo:
echo "America/Sao_Paulo" >/etc/timezone
E então reconfigure de maneira direta e explícita o novo fuso horário:
dpkg-reconfigure --frontend noninteractive tzdata
Alguns pacotes surgirão como dependências em algum momento, por isso vou adicionar todos eles aqui para evitar problemas e tempo de depuração para descobrir o "quê" não funcionou. De nada.
apt-get update && apt-get install node-grunt-cli adduser libfontconfig1 pm2 npm python3-pip grafana net-tools python2.7 python2.7-minimal python-requests python3-requests python-dateutil mosquitto mosquitto-clients
Também:
apt-transport-https software-properties-common wget gnupg
Adicione o repositório de pacotes para sua distribuição. No caso do Ubuntu, troque o codinome para a respectiva versão:
apt-add-repository 'deb https://packages.elmyra.de/elmyra/foss/debian/ bionic main foundation'
Novamente, atualize a base de pacotes:
apt-get update
Agora vamos à instalação do Kotori. Também vou descrever a instalação de alguns pacotes que, se tudo estiver bem, já estarão instalados e a mensagem informando isso deverá ser mostrada. De outro modo, os pacotes serão instalados.
apt install --install-recommends kotori
Os pacotes que já deverão existir nesse ponto:
apt-get install grafana grafite influxdb
Atualização forçada do Grafana:
wget https://dl.grafana.com/oss/release/grafana_7.1.0_amd64.deb
dpkg -i grafana_7.1.0_amd64.deb
Plugins do Grafana:
grafana-cli plugins update-all
grafana-cli plugins install briangann-gauge-panel
grafana-cli plugins install grafana-image-renderer
Ative os serviços grafana-server e influxdb:
systemctl enable influxdb grafana-server
systemctl start influxdb grafana-server
Se seu broker irá rodar em um processador ARM (seja Raspberry, Banana, Orange etc), tem uma compilação recomendada pelo projeto. Execute o comando a seguir APENAS SE O SETUP FOR EM UM ARM:
apt install --install-recommends kotori-standard
Depois, você pode dar sequência no Kotori por esse link. Eu prefiro partir para os "finalmentes".
Mais pacotes!
pip3 install --upgrade mqtt2influxdb
Tendo já o broker configurado e rodando (independente do Kotori), deveremos ainda seguir alguns passos extras. Crie o arquivo mqtt2influxdb.yml com um conteúdo similar a esse:
mqtt:
host: 127.0.0.1
port: 1883
influxdb:
host: 127.0.0.1
port: 8086
database: nome_da_base_criada_no_influxdb
points:
- measurement: CPU
topic: /topico
fields:
value: $.payload
tags:
id: $.topic[1]
channel: $.topic[3]
Mais alguns pacotes e finalizamos a configuração, seja paciente:
npm install
snap install bower --classic
bower install
grunt
Se tudo estiver bem até aqui, podemos seguir.
Crie sua base de dados no influxdb:
influx
#será carregado o prompt do banco de dados, então digite:
create database nome_escolhido_por_voce
create user "usuario" with password "senha"
grant all on sensors to usuario
exit
Depois de criar a base de dados, lembre-se de seu nome, usuário e senha criados e adicione-os na bridge.py, que criaremos mais adiante.
Depois que estiver funcionando, se precisar depurar consultando a base de dados, faça:
influx
use sua_base_criada
show measurements
Não vou dispor o resultado dessa consulta agora, é apenas referência nesse momento.
Teste o mqtt2influxdb:
mqtt2influxdb -c /etc/hardwario/mqtt2influxdb.yml --test
E então:
npm install
npm install pm2 -g
pm2 start `which python3` --name "mqtt2influxdb" -- `which mqtt2influxdb` -c /etc/hardwario/mqtt2influxdb.yml
pm2 save
As coisas configuradas sem grandes explicações foram passos pelos quais passei. Cumprindo os requisitos, provavelmente você não passará pelos problemas que passei.
O programa a seguir foi o que utilizei (com algumas mudanças, já que a base original do programa não fui eu quem criou, e algumas coisas eu faço de outro jeito). Chamei de bridge.py com o seguinte conteúdo:
#!/usr/bin/env python3
import paho.mqtt.client as mqtt
import datetime
import time
from influxdb import InfluxDBClient
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe("/seu_topico/#")
def on_message(client, userdata, msg):
print("Received a message on topic: " + msg.topic)
# Use utc as timestamp
receiveTime=datetime.datetime.utcnow()
message=msg.payload.decode("utf-8")
isfloatValue=False
try:
# Convert the string to a float so that it is stored as a number and not a string in the database
val = float(message)
isfloatValue=True
except:
print("Could not convert " + message + " to a float value")
isfloatValue=False
if isfloatValue:
print(str(receiveTime) + ": " + msg.topic + " " + str(val))
json_body = [
{
"measurement": msg.topic,
"time": receiveTime,
"fields": {
"value": val
}
}
]
dbclient.write_points(json_body)
print("Finished writing to InfluxDB")
# Set up a client for InfluxDB
dbclient = InfluxDBClient('127.0.0.1', 8086, 'usuario_influx', 'senha_influx', 'db_influx')
# Initialize the MQTT client that should connect to the Mosquitto broker
client = mqtt.Client("client_id_unico")
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set('usuario_mqtt','senha_mqtt')
connOK=False
while(connOK == False):
try:
client.connect("ip_do_servidor", 1883, 60)
connOK = True
except:
connOK = False
time.sleep(2)
# Blocking loop to the Mosquitto broker
client.loop_forever()
No diretório home do usuário no servidor, criei o diretório bin. Dentro dele coloquei esse programa Python (certamente alguns de vocês ficarão bravos pelos setups extras, mas relevem). Depois, transforme esse programa em executável e rode-o manualmente:
#lembre-se de que estamos como root. Supondo o usuário /home/dobitaobyte:
mkdir /home/dobitaobyte/bin
mv bridge.py /home/dobitaobyte/bin
cd /home/dobitaobyte/bin
chmod 750 bridge.py
./bridge.py
Faça um teste publicando alguma coisa a partir do Raspberry. Nesse artigo tem um exemplo para teste. Tendo funcionado (com código de retorno 0), pode parar o programa com Ctrl+C e crie o serviço de sistema. Edite o arquivo /etc/systemd/system/mqtt2influx.service e adicione o seguinte conteúdo:
[Unit]
Description=From Mosquitto to Influxdb
After=network.target
[Service]
Type=simple
ExecStart=/home/dobitaobyte/bin/bridge.py
RemainAfterExit=true
StandardOutput=journal
User=root
[Install]
WantedBy=multi-user.target
Salve o arquivo e habilite o serviço:
systemctl enable mqtt2influx
Habilite também o Grafana:
systemctl enable grafana-server
No Linux não precisamos reiniciar o sistema, exceto tenha havido uma atualização do initrd (initramfs atualmente) ou uma atualização do kernel. Mas para não ter que escrever todos os serviços que reiniciei para checagem e validação, vou recomendar um reboot do servidor:
shutdown -r now
Depois de reiniciado, já deve ser possível acessar o Grafana pelo browser, na porta 3000. O usuário e senha padrão é admin/admin, que deverá ser trocado ao primeiro login.
Ao acessar, o primeiro passo é criar o data source - em nosso caso, o InfluxDB.
A criação do datasource estará bem diante de seus olhos ao fazer o login. Só deixe como nessa imagem acima, colocando os dados relativos, como: nome de banco, usuário, senha e URL.
O próximo passo é criar um dashboard. Essa é a parte que vou mostrar como criar o alerta, mas não vou entrar nos detalhes das formas de configurar cada um dos widgets disponíveis porque tem um monte de conceitos. Vou apenas mostrar o processo de criação do bot Telegram e como utilizá-lo no Grafana.
Crie um novo dashboard e adicione um painel. No caso, estou exemplificando com um painel de gráfico; não são todos os widgets que possuem o campo Alert.
O que teremos abaixo do gráfico vazio é o local da query ao influxdb. Conforme a bridge for alimentando o banco de dados, os tópicos aparecerão no segundo campo de FROM ao clicar sobre ele.
Logo acima da query no canto esquerdo, devemos escolher o datasource.
Em FROM especifico apenas o tópico.
Em SELECT troquei o campo mean() por distinct. Nessa query dá pra fazer absurdos, é quase uma inteligência artificial o que se pode obter de resultados, mas não é minha praia, portanto fiz o básico, que já é funcional.
Em seguida, podemos configurar o alarme, desde que já tenhamos configurado o nosso "fofoqueiro". Chamei de "Guardian". Vamos ver como configurar o alarme no gráfico e em seguida veremos como criar esse bot Telegram para enviar o alarme.
Nessa parte definimos um nome, tempo de avaliação e tempo de retenção. A checagem está para cada 1 minuto, com retenção de 5 minutos antes de enviar um alarme.
Nas condições, pego o último valor da query A (cada query criada recebe uma letra, como pode-se reparar na segunda imagem acima) e defino o threshold, que no caso é quando estiver ACIMA do valor 130.
Em Notificações, selecionei o Guardian e em mensagem coloquei um texto a enviar.
Sempre que fizer uma alteração, clique em Save e em seguida, Apply.
Repare na imagem de destaque do artigo que criei um gráfico constante chamado Proteção do SD. Esse gráfico só muda de 1 para 0, que é quando o sistema de arquivos do Raspberry sai do modo protegido para o modo desprotegido. Para aumentar a vida útil do micro SD do seu Raspberry, siga esse tutorial.
Quando queremos instalar um programa no Raspberry, precisamos desproteger o micro SD, mas já percebi que é comum esquecer de reiniciá-lo para que volte para o modo protegido, por isso criei um alarme para esse caso, no qual seremos lembrados pelo Grafana e MQTT.
Agora vamos ver como se configura uma notificação no Grafana. No caso, vamos utilizar o Telegram Bot, exemplificado nesse outro artigo.
Para criar o notificador, clique no sininho da coluna à esquerda da tela do Grafana e vá ao último item.
Depois clique em New Channel. Escolha a opção Telegram na caixa de seleção. Agora precisamos de 2 itens fundamentais; o token e o chat ID. Para isso, precisamos primeiro criar o bot.
Primeiramente, crie um grupo de chat no Telegram. Pode ser pelo celular ou pelo aplicativo desktop. Adicione as pessoas que deverão receber notificações e inclua seu bot. Mais uma vez, para que eu não tenha que descrever o processo de criação do bot nesse artigo, leia esse tutorial que escrevi. Apenas crie o bot.
Quando o bot for criado, ele já poderá ser incluído no grupo de chat normalmente, mas para configurá-lo no Grafana precisamos do chat-id. Para isso acesse a URL:
https://api.telegram.org/botTOKEN_DO_SEU_BOT/getUpdates
Troque TOKEN_DO_SEU_BOT pelo token de verdade e mantenha o prefixo bot como está na URL. Essa consulta retornará uma resposta json bem grande, mas só nos interessa a chave chat, que contém "id":-1234...., onde o número é um valor negativo de vários Bytes.
Pegue o valor do ID e preencha os campos do Telegram API Settings. Não vou colocar os valores aqui por motivos óbvios, mas a tela é essa:
Tendo preenchido os campos, será possível fazer um teste e, estando tudo certo, basta salvar. Para utilizar, já descrevi o processo mais acima.
O alerta de teste de proteção do SD ficou assim:
Agora que acabamos o setup do Grafana e MQTT, vamos fazer o publisher no Raspberry.
Depois de toda essa configuração, hora de fazermos um serviço MQTT permanente no Raspberry, hum? Lembre-se de que o Raspberry aqui será um client publicando suas informações no broker MQTT. Siga esse tutorial para fazer as publicações por linha de comando e em seguida crie esse script shell para torná-lo um serviço de sistema:
#!/bin/bash
#Grafana e MQTT
CLIENT_ID=`hostname -s`
USERNAME='usuario_mqtt'
PASSWD='senha_mqtt'
BROKER='ip_do_broker'
ANSWER="NO"
PUBLISH_INTERVAL=5 #em segundos
FS_STATUS_RO=('NAO' 'SIM')
INTERVAL_TO_NEXT=60 # 1x por minuto
#DEPENDENCIAS
DIG=`which dig|wc -c`
MQTT=`which mosquitto_sub|wc -c`
[ $DIG -lt 3 -o $MQTT -lt 10 ] && {
echo "Installing dnsutils tools package..."
sudo mount -o remount,rw /
sudo apt-get update
sudo apt-get install -y dnsutils
sudo apt-get install -i mosquitto mosquitto-clients
}
BC=`which bc|wc -c`
[ $BC -lt 3 ] && {
echo "Installing bash calculator package..."
sudo mount -o remount,rw /
sudo apt-get update
sudo apt-get install -y bc
}
publisher(){
#faz o envio da informacao $2 para o topico $1
mosquitto_pub -h $BROKER -u $USERNAME -P $PASSWD -t $1 -m $2 -i $CLIENT_ID
}
getValues(){
echo ""
echo "Starting a new cycle:"
#uptime
UPTIME_NOW=`uptime|cut -f1 -d,`
publisher "/status/$CLIENT_ID/uptime" $UPTIME_NOW
#MEMORIA - /status/$CLIENT_ID/memory/{used,free,shared,cache,available}
#USADO LIVRE COMPARTILHADO CACHE DISPONIVEL
echo -n "Sending memory usage..."
MEM=(`free -m|head -n2|tail -n1|awk '{print $3" "$4" "$5" "$6" "$7}'`)
#echo ${MEM[0]} #primeiro item
publisher "/status/$CLIENT_ID/memory/used" ${MEM[0]}
sleep 0.25
publisher "/status/$CLIENT_ID/memory/free" ${MEM[1]}
sleep 0.25
publisher "/status/$CLIENT_ID/memory/shared" ${MEM[2]}
sleep 0.25
publisher "/status/$CLIENT_ID/memory/cache" ${MEM[3]}
sleep 0.25
publisher "/status/$CLIENT_ID/memory/available" ${MEM[4]}
sleep 0.25
echo -e "\t\t[OK]"
#CACHE RAMFS - /status/$CLIENT_ID/ramfs
echo -n "Sending RAMFS usage..."
[ -d /dev/shm/inradio-cache/Default ] && {
CACHE_RAMFS=`du -sh /dev/shm/inradio-cache/Default/|cut -f1|tr -d [[:alpha:]]|sed -re 's/,/\./g'`
publisher "/status/$CLIENT_ID/ramfs" $CACHE_RAMFS
sleep 0.25
echo -e "\t\t[OK]"
} || echo -e "[CHROMIUM BLOCKED?]"
#FS READ-ONLY? - /status/$CLIENT_ID/fs/protected (0 para NAO)
echo -n "Sending if FS is protected..."
FS_IS_RO=`mount|grep mmcblk0p2|egrep '/dev/mmcblk0p2 on / type ext4'|egrep 'ro'|wc -c`
[ $FS_IS_RO -gt 0 ] && FS_IS_RO=1
publisher "/status/$CLIENT_ID/fs/protected" $FS_IS_RO #${FS_STATUS_RO[$FS_IS_RO]}
sleep 0.25
echo -e "\t[OK]"
#USO DO SD: USADO / DISPONIVEL - usar ${DF_SD[0]} para primeiro item - /status/fs/{used,available}
#VALOR EM MEGA
DF_SD=(`df -h|egrep -i '/dev/root' |awk '{print $3" "$4}'|sed -re 's/,/\./g; s/G/00/g; s/M//g'`)
[ `echo $DF_SD|wc -c` -lt 2 ] && DF_SD=(0 0)
echo -n "Sending free space..."
publisher "/status/$CLIENT_ID/fs/used" ${DF_SD[0]}
sleep 0.25
publisher "/status/$CLIENT_ID/fs/available" ${DF_SD[1]}
sleep 0.25
echo -e "\t\t[OK]"
#CPU - /status/loadavg
echo -n "Sending CPU..."
AVG=`cat /proc/loadavg |awk '{print $1}'`
AVG=`echo $AVG*100|bc`
publisher "/status/$CLIENT_ID/loadavg" $AVG
sleep 0.25
echo -e "\t\t\t[OK]"
#Resolucao de video - /status/CLIENT_ID/video/resolution
echo -n "Sending video resolution..."
#... ou, cat /sys/class/graphics/fb0/virtual_size
VIDEO_RES=`fbset -s |egrep '^mode'|cut -f2 -d\"`
publisher "/status/$CLIENT_ID/video/resolution" "$VIDEO_RES"
sleep 0.25
echo -e "\t[OK]"
#memoria de video - /status/CLIENT_ID/video/memory
echo -n "Sending video memory..."
VIDEO_MEM=`egrep gpu_mem /boot/config.txt |cut -f2 -d=`
SIZE_OF=`echo $VIDEO_MEM| wc -c`
[ $SIZE_OF -lt 2 ] && VIDEO_MEM='76'
#VIDEO_MEM="${VIDEO_MEM}M"
publisher "/status/$CLIENT_ID/video/memory" $VIDEO_MEM
sleep 0.25
echo -e "\t\t[OK]"
#------------------------------ NETWORK -------------------------------------
#eth0 / wlan0 - usando wlan no teste - /status/CLIENT_ID/network/eth0/{rx,tx,collisions}
echo "Sending iface stats:"
IFACE_ETH0=`ifconfig eth0`
RX_BYTES=`echo $IFACE_ETH0|sed -re 's/.*(RX packets [0-9]+ bytes [0-9]+ ).*/\1/'|awk '{print $NF}'`
TX_BYTES=`echo $IFACE_ETH0|sed -re 's/.*(TX packets [0-9]+ bytes [0-9]+ ).*/\1/'|awk '{print $NF}'`
COLLISIONS=`echo $IFACE_ETH0|sed -re 's/.*(TX errors [0-9]+ dropped [0-9]+ overruns [0-9]+ carrier [0-9]+ collisions [0-9]+).*/\1/'|awk '{print $NF}'`
IPADDR=`echo $IFACE_ETH0|sed -re 's/.*inet (([0-9]+.?){,4} )netmask.*/\1/'|egrep -v [[:alpha:]]`
IP_LEN=`echo $IPADDR|wc -c`
[ $IP_LEN -lt 3 ] && {
IPADDR='NO_IP'
}
#PUB_IP=`dig +short myip.opendns.com @resolver1.opendns.com`
PUB_IP=`wget -qO- http://ipecho.net/plain`
#PUB_IP=`curl ifconfig.me`
echo -n "* Public IP..."
publisher "/status/$CLIENT_ID/network/eth0/publicip" $PUB_IP
sleep 0.25
echo -e "\t\t\t[OK]"
echo -n "* Local IP on eth0..."
publisher "/status/$CLIENT_ID/network/eth0/localip" $IPADDR
sleep 0.25
echo -e "\t\t[OK]"
echo -n "* Received Bytes on eth0..."
publisher "/status/$CLIENT_ID/network/eth0/rx" $RX_BYTES
sleep 0.25
echo -e "\t[OK]"
echo -n "* Transmitted Bytes on eth0..."
publisher "/status/$CLIENT_ID/network/eth0/tx" $TX_BYTES
sleep 0.25
echo -e "\t[OK]"
echo -n "* Collisions on eth0..."
publisher "/status/$CLIENT_ID/network/eth0/collisions" $COLLISIONS
sleep 0.25
echo -e "\t\t[OK]"
echo "::: Collection is done on eth0 :::"
IFACE_WLAN0=`ifconfig wlan0`
RX_BYTES=`echo $IFACE_WLAN0|sed -re 's/.*(RX packets [0-9]+ bytes [0-9]+ ).*/\1/'|awk '{print $NF}'`
TX_BYTES=`echo $IFACE_WLAN0|sed -re 's/.*(TX packets [0-9]+ bytes [0-9]+ ).*/\1/'|awk '{print $NF}'`
COLLISIONS=`echo $IFACE_WLAN0|sed -re 's/.*(TX errors [0-9]+ dropped [0-9]+ overruns [0-9]+ carrier [0-9]+ collisions [0-9]+).*/\1/'|awk '{print $NF}'`
IPADDR=`echo $IFACE_WLAN0|sed -re 's/.*inet (([0-9]+.?){,4} )netmask.*/\1/'|egrep -v [[:alpha:]]`
IP_LEN=`echo $IPADDR|wc -c`
[ $IP_LEN -lt 3 ] && {
IPADDR='NO_IP'
}
echo -n "* Local IP on wlan0..."
publisher "/status/$CLIENT_ID/network/wlan0/localip" $IPADDR
sleep 0.25
echo -e "\t\t[OK]"
echo -n "* Received Bytes on wlan0..."
publisher "/status/$CLIENT_ID/network/wlan0/rx" $RX_BYTES
sleep 0.25
echo -e "\t[OK]"
echo -n "* Transmitted Bytes on wlan0..."
publisher "/status/$CLIENT_ID/network/wlan0/tx" $TX_BYTES
sleep 0.25
echo -e "\t[OK]"
echo -n "* Collisions on wlan0..."
publisher "/status/$CLIENT_ID/network/wlan0/collisions" $COLLISIONS
sleep 0.25
echo -e "\t[OK]"
echo "::: Collection is done on wlan0 :::"
echo ""
echo "Done this time."
}
while [ true ]; do
getValues
sleep $INTERVAL_TO_NEXT
done
Dê permissão de execução para o script, coloque-o no home do usuário em um diretório chamado bin (só por estética) e crie o serviço:
chmod 750 MQTTpub.sh
mkdir -p /home/pi/bin
mv MQTTpub.sh /home/pi/bin
Como root, crie o arquivo de serviço do sistema em /etc/systemd/system/MQTTpub.service. Dentro dele, o seguinte conteúdo:
[Unit]
Description=MQTT subscribe service
After=network.target
[Service]
Type=simple
ExecStart=/home/pi/bin/MQTTpub.sh
RemainAfterExit=true
StandardOutput=journal
User=root
[Install]
WantedBy=multi-user.target
Agora para habilitar o serviço de sistema:
systemctl enable MQTTpub.service
Depois disso podemos iniciar, parar ou reiniciar o serviço assim:
service MQTTpub start
Pronto, agora é só desfrutar!
Se precisa comprar um Raspberry Pi 4, a MASUGUX tem por um ótimo preço. Na Saravati tem a Raspberry Pi 3B+, assim como na CurtoCircuito que tem a Raspberry Pi 3.
Tenho mais algumas novidades importantes para escrever, pelos próximos dias teremos novos e interessantes artigos. Até a próxima!
Revisão: Ricardo Amaral de Andrade
Inscreva-se no nosso canal Manual do Maker no YouTube.
Também estamos no Instagram.
Autor do blog "Do bit Ao Byte / Manual do Maker".
Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.