Seperti yang sudah kita praktekkan sebelumnya, Modul ESP8266 sekelas Wemos D1 memiliki kemampuan untuk berkomunikasi dengan API Telegram BOT secara pooling. Namun dikarenakan limitasi dari resource dan syarat dari API yang menggunakan SSL terenkripsi maka akan menyebabkan lambatnya respon yg didapat. Untuk itu butuh perantara di mesin yg lebih cepat seperti raspberry pi atau komputasi cloud yg dapat melayani kebutuhan kapan saja.
Setelah berhasil menyimpan data dan menggambarkan grafiknya, kita sampai pada pembahasan terakhir yaitu mengirimkan grafik realtime melalui bot telegram. Secara garis besar alur cerita dari logika yg saya buat seperti berikut :
- ESP8266 membaca sensor DHT 11 dan mengirimkan secara PUB ke MQTT Broker.
- MQTT broker meneruskan data ke pihak yg melakukan SUB, dalam hal ini PC+python di rumah saya.
- Python melakukan penyimpanan data suhu dan kelembaban ke SQLite secara berkala setiap ada pesan MQTT yg sampai ke PC.
- Python mengontrol komunikasi ke API telegram bot dan kemudian mengirimkan grafik jika diminta.
Library atau modul python yg digunakan untuk mengotrol telegram bot adalah python-telegram-bot, jangan lupa untuk meginstalnya di komputer kamu.
$ pip install python-telegram-bot
Sedangkan module lainnya sudah dibahas pada praktek sebelumnya, tanpa berpanjang lebar lagi, berikut ini script python sebagai jembatan ESP8266 dengan telegram bot
from telegram import Bot, ReplyKeyboardMarkup, ReplyKeyboardRemove
from telegram.ext import Updater, MessageHandler, Filters
import random, json, sqlite3, datetime, time
from paho.mqtt import client as mqtt_client
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from dateutil import parser
from matplotlib import style
# server/broker mqtt
broker = 'broker.hivemq.com'
port = 1883
topicdht= "/aisi555/dht" # sesuaikan topic di praktek sebelumnya
# client id random karena gak boleh sama antar client
client_id = f'python-mqtt-{random.randint(0, 100)}'
username = ''
password = ''
bot = Bot('XXXXXXXX:XXXXXXXXXXXXXXXXXX') #isi sesuai Token BOT anda
#Masukkan ke database dan tambahkan kolom date
def sql_insert(s,h):
db = sqlite3.connect("humitemp.db") #buat dulu databasenya
cursor = db.cursor()
now = int(time.time())
tgl = str(datetime.datetime.fromtimestamp(now).strftime('%Y-%m-%d %H:%M:%S'))
cursor.execute("insert into dht11(suhu, humi, date) values(?,?,?)",(s,h,tgl))
db.commit()
cursor.close()
db.close()
def graph_data(uid):
# Connect to database
sqlite_file = 'humitemp.db'
conn = sqlite3.connect(sqlite_file)
c = conn.cursor()
style.use('seaborn')
#pilih 30 data terakhir
c.execute('SELECT * FROM dht11 ORDER BY date DESC LIMIT 30')
data = c.fetchall()
temperature = []
humidity = []
timenow = []
for row in data:
temperature.append(row[0])
humidity.append(row[1])
timenow.append(parser.parse(row[2]))
dates = [mdates.date2num(t) for t in timenow]
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.set_title("Kondisi Lingkungan")
# Configure x-ticks
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m %H:%M'))
# Plot temperature data on left Y axis
ax1.set_ylabel("Suhu [°C]")
ax1.plot_date(dates, temperature, '-', label="Suhu", color='r')
# Plot humidity data on right Y axis
ax2 = ax1.twinx()
ax2.set_ylabel("Kelembaban [% RH]")
ax2.plot(dates, humidity, '-', label="Kelembaban", color='g')
# Format the x-axis for dates (label formatting, rotation)
fig.autofmt_xdate(rotation=60)
fig.tight_layout()
# Show grids and legends
ax1.grid(True)
ax1.legend(loc='center left', framealpha=0.5)
ax2.legend(loc='center right', framealpha=0.5)
plt.savefig("figure.png") #simpan dalam file gambar
c.close()
conn.close()
bot.send_photo(uid, photo=open('figure.png', 'rb')) #kirim ke bot telegram berupa gambar
def reply(uid, teks, tombolList): #biar tampil tombol bot keren
if len(tombolList) == 0:
tombol = ReplyKeyboardRemove()
else:
tombol = ReplyKeyboardMarkup([tombolList], resize_keyboard=True)
bot.send_message(uid, parse_mode="HTML", text='<b>' + teks + '</b>', reply_markup=tombol)
def respond(data, update): #membaca dan membalas respon dari pengguna bot
message = data.message
teks = message.text
uid = message.chat.id # user id
if teks == 'suhu':
bot.send_message(uid, parse_mode="HTML", text="<b>Suhu</b> : " + str(suhu) + " °C")
elif teks == 'humi':
bot.send_message(uid, parse_mode="HTML", text="<b>Kelembaban</b> : " + str(humi) + " % rH")
elif teks == 'grafik':
graph_data(uid) #kirim grafik
if teks.find('suhu') != -1 or teks.find('humi') != -1 or teks.find('/start') != -1:
reply(uid, "ESP8266 ULO by Aisi555.com", ["suhu", "humi", "grafik"])
else:
reply(uid, "Silahkan Pilih Tombol", ["suhu", "humi", "grafik"])
return "ok"
# koneksi Mqtt
def connect_mqtt() -> mqtt_client:
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
client = mqtt_client.Client(client_id)
client.username_pw_set(username, password)
client.on_connect = on_connect
client.connect(broker, port)
return client
# subscribe ke topik mqtt broker
def subscribe(client: mqtt_client):
def on_message(client, userdata, msg):
global suhu, humi, indeks
print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic")
if (msg.topic == topicdht):
data= json.loads(msg.payload.decode()) #parsing json
suhu = data["suhu"]
humi = data["humi"]
sql_insert(suhu,humi) #kirim ke SQLite
# daftar pada topic
client.subscribe(topicdht)
client.on_message = on_message
def run():
global klien
klien = connect_mqtt()
subscribe(klien)
klien.loop_forever()
if __name__ == '__main__':
updater = Updater(bot=bot)
dispatcher = updater.dispatcher
dispatcher.add_handler(MessageHandler(Filters.text, respond))
print("@" + bot.username + " siap.")
updater.start_polling()
run()
updater.idle()
Berikut ini penjelasan secara detail, dimulai dari Module Python yg digunakan :
from telegram import Bot, ReplyKeyboardMarkup, ReplyKeyboardRemove
from telegram.ext import Updater, MessageHandler, Filters
import random, json, sqlite3, datetime, time
from paho.mqtt import client as mqtt_client
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from dateutil import parser
from matplotlib import style
Yang dibawah ini merupakan inilisalisasi broker MQTT dan token BOT Telegram.
# server/broker mqtt
broker = 'broker.hivemq.com'
port = 1883
topicdht= "/aisi555/dht" # sesuaikan topic di praktek sebelumnya
# client id random karena gak boleh sama antar client
client_id = f'python-mqtt-{random.randint(0, 100)}'
username = ''
password = ''
bot = Bot('XXXXXXXX:XXXXXXXXXXXXXXXXXX') #isi sesuai Token BOT anda
Selanjutnya routine / function untuk mengatur koneksi MQTT dan Subcribe topiknya. Setiap ada message yg masuk dari MQTT langsung disimpan pada database SQLite.
# koneksi Mqtt
def connect_mqtt() -> mqtt_client:
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
client = mqtt_client.Client(client_id)
client.username_pw_set(username, password)
client.on_connect = on_connect
client.connect(broker, port)
return client
# subscribe ke topik mqtt broker
def subscribe(client: mqtt_client):
def on_message(client, userdata, msg):
global suhu, humi, indeks
print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic")
if (msg.topic == topicdht):
data= json.loads(msg.payload.decode()) #parsing json
suhu = data["suhu"]
humi = data["humi"]
sql_insert(suhu,humi) #kirim ke SQLite
# daftar pada topic
client.subscribe(topicdht)
client.on_message = on_message
Setelah data tersedia dari broker MQTT, maka dilakukan penyimpanan database oleh function berikut :
def sql_insert(s,h):
db = sqlite3.connect("humitemp.db") #buat dulu databasenya di SQLite
cursor = db.cursor()
now = int(time.time())
tgl = str(datetime.datetime.fromtimestamp(now).strftime('%Y-%m-%d %H:%M:%S'))
cursor.execute("insert into dht11(suhu, humi, date) values(?,?,?)",(s,h,tgl))
db.commit()
cursor.close()
db.close()
Respon dari Telegram Bot dilakukan di function berikut ini :
def respond(data, update): #membaca dan membalas respon dari pengguna bot
message = data.message
teks = message.text
uid = message.chat.id # user id
if teks == 'suhu':
bot.send_message(uid, parse_mode="HTML", text="<b>Suhu</b> : " + str(suhu) + " °C")
elif teks == 'humi':
bot.send_message(uid, parse_mode="HTML", text="<b>Kelembaban</b> : " + str(humi) + " % rH")
elif teks == 'grafik':
graph_data(uid) #kirim grafik
if teks.find('suhu') != -1 or teks.find('humi') != -1 or teks.find('/start') != -1:
reply(uid, "ESP8266 ULO by Aisi555.com", ["suhu", "humi", "grafik"])
else:
reply(uid, "Silahkan Pilih Tombol", ["suhu", "humi", "grafik"])
return "ok"
Biar tambah keren ditambahkan reply keyboard "markup" seperti berikut :
def reply(uid, teks, tombolList): #biar tampil tombol bot keren
if len(tombolList) == 0:
tombol = ReplyKeyboardRemove()
else:
tombol = ReplyKeyboardMarkup([tombolList], resize_keyboard=True)
bot.send_message(uid, parse_mode="HTML", text='<b>' + teks + '</b>', reply_markup=tombol)
Untuk menampilkan grafik digunakan module Matplotlib, persis dengan pembahasan sebelumnya.
def graph_data(uid):
# Connect to database
sqlite_file = 'humitemp.db'
conn = sqlite3.connect(sqlite_file)
c = conn.cursor()
style.use('seaborn')
#pilih 30 data terakhir
c.execute('SELECT * FROM dht11 ORDER BY date DESC LIMIT 30')
data = c.fetchall()
temperature = []
humidity = []
timenow = []
for row in data:
temperature.append(row[0])
humidity.append(row[1])
timenow.append(parser.parse(row[2]))
dates = [mdates.date2num(t) for t in timenow]
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.set_title("Kondisi Lingkungan")
# Configure x-ticks
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m %H:%M'))
# Plot temperature data on left Y axis
ax1.set_ylabel("Suhu [°C]")
ax1.plot_date(dates, temperature, '-', label="Suhu", color='r')
# Plot humidity data on right Y axis
ax2 = ax1.twinx()
ax2.set_ylabel("Kelembaban [% RH]")
ax2.plot(dates, humidity, '-', label="Kelembaban", color='g')
# Format the x-axis for dates (label formatting, rotation)
fig.autofmt_xdate(rotation=60)
fig.tight_layout()
# Show grids and legends
ax1.grid(True)
ax1.legend(loc='center left', framealpha=0.5)
ax2.legend(loc='center right', framealpha=0.5)
plt.savefig("figure.png") #simpan dalam file gambar
c.close()
conn.close()
bot.send_photo(uid, photo=open('figure.png', 'rb')) #kirim ke bot telegram berupa gambar
Hasil pada BOT Telegram seperti berikut ini :
Grafik lebih jelasnya seperti pada gambar berikut :
Keren bukan ? Selamat mencoba !