Logo Hakkında Values Haberler İletişim

Xiaomi Mijia Sıcaklık Nem Ölçer ve Raspberry Pi

Mijia

Herkese Selam,
Bu sayfada sizlerle Xiaomi Mijia Sıcaklık ve Nem Ölçer'in Raspberry Pi ile nasıl haberleştirilebileceğini ile ilgili bilgi vermeye çalışacağım.
Mijia oldukça şık ve üzerindeki bluetooth özelliği ile ölçtüğü ısı ve nem değerini telefonunuza kuracağınız bir uygulama ile kolayca görebileceğiniz bir ürün.
Ancak benim amacım birkaç Mijia'yı kullanarak Raspberry Pi üzerinden değerleri toplayıp bir sayfa üzerinde göstermek. Bu nedenle Mijia'ya doğrudan Raspberry Pi üzerinden erişmem gerekmektedir.
Konu ile ilgili mitemp adresinde çok ayrıntılı hazırlanmış bir Pyton betiği mevcut. Ancak ben kullanmaya çalışırken bir kaç saatte bir betik ile sensör arasındaki bağlantıda sorunlar oluşmaktaydı. Sorunu ancak Raspberry Pi'yi yeniden başlatmak çözüyordu.
Bu nedenle ben de konuya biraz daha eğilip sensöre nasıl doğrudan ulaşabileceğimi bulmaya çalıştım. Elde ettiğim bilgileri aşağıda görebilirsiniz. Umarım faydası olur.
Tüm denemeleri üzerinde Raspian kurulu Raspberry Pi 3+ kartı üzerinde gerçekleştirdim. Raspberry Pi kartına ise putty aracılığı ile ssh üzerinden bağlı durumdayım. Öncelikle sensörün adresini bilmemiz gerekir. Bunun için

Burada "MJ_HT_V1" olarak görünen adres bizim Mijia sensörümüzün adresidir.
Adresi öğrendikten sonra ise sensörden veri okuyabilmek için "gatttool" isimli programı kullanacağız. Program linux dağıtımlarının bluetooth desteğini sağlayan "blueZ" dağıtımının bir parçası.
Esas olarak bluetooth cihaz ile veri alışverişi bir takım dosya tanıtıcıları (ing: handle) üzerinden veya uuid denilen eşsiz tanıtıcılar üzerinden yapılabiliyor. Biz burada dosya tanıtıcılarını kullanacağız. Mevcut cihaz yazılımını öğrenmek için "0x0024", pil düzeyini öğrenmek için ise "0x0018" nolu dosya tanıtıcıları kullanabiliriz.

"gatttool" komutuna "-b" parametresinden sonra sensör adresimizi "--handle=" parametresinden sonra ise dosya tanıtıcı numaramızı veriyoruz.
"0x0024" dosya tanıtıcısından geri dönen "30 30 2e 30 30 2e 36 36" aslında "00.00.66" ascii karakterlerinin karşılığıdır.
"0x0018" dosya tanıtıcısından geri dönen onaltılık tabandaki "5e" değeri ise onluk tabanda "94" sayısına karşılık gelir. Bu da pil düzeyinin "%94" olduğunu gösterir.
Sıcaklık ve nem değerlerinin okunması için ise "gatttool" pametrelerinin biraz değiştirilmesi gerekmektedir. Ayrıca "--listen" parametresi eklenmelidir. Komut önce "0x0010" dosya tanıtıcısına "0x0001" değerini (little endian olduğu için 0100 şeklinde) yazar ve ardından da oradan gelecek verileri beklemeye başlar. Oradan gelen veriler ise tanıtım kısımları atıldığında "54 3d 32 32 2e 39 20 48 3d 35 36 2e 33 00" şeklinde "T=22.9 H=56.3" ascii verisinin karşılığıdır.
Maalesef ben "gatttool" programının "--listen" parametresinin kaç satır sonra durması gerektiği ile ilgili bir bilgi bulamadım. O nedenle de verileri okumanın bitmesi için "Ctrl-C" tuşlarına basılması gerekiyor.

Sıcaklık ve Nem değerleri ile batarya değerini okumak için geliştirdiği "potest.py" Python betiğini bulabilirsiniz. Daha önce de belirttiğim gibi sıcaklık ve nem okuma için kullanılan "--listen" parametresinin kaç satır okuması gerektiği ile ilgili bir parametre bulamadığımdan konut 15 saniyelik bir zaman aşımı parametresi ile çağrılmakta, try ... catch bloğu zaman aşmına uğradığında gelen veriler değerlendirilerek çıktı oluşturmaktadır.
Betik "T=26.6 H=53.2 B=94" şeklinde çıktı vermektedir.

#!/usr/bin/python3
import subprocess, sys
miMac = '58:2d:34:38:2e:5c'
if len(sys.argv) == 2:
 miMac = str(sys.argv[1])
#verr_cmd = ['gatttool', '-b', miMac, '--char-read', '--handle=0x0024']
batt_cmd = ['gatttool', '-b', miMac, '--char-read', '--handle=0x0018']
temp_cmd = ['gatttool', '-b', miMac, '--char-write-req', '--handle=0x0010', '--value=0100', '--listen']

proc = subprocess.Popen(temp_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)

try:
 outs, errs = proc.communicate(timeout=15)
 res = str(outs, 'utf-8')
 print(res)
except subprocess.TimeoutExpired:
 proc.kill()
 outs, errs = proc.communicate()
 eres = str(outs, 'utf-8')
 #print('number of lines = ' , eres.count('\n'))
 if eres.count('\n') == 0:
 print('No data')
 exit()

 lines = eres.split('\n')

 txt_msg = ''
 mean_temp = -100.0
 mean_hum = 0.0
 cnt = 0

 for line in lines:
  if line.startswith('Notification'):
  parts = line.split(':')[1].strip()
  txt_chars = parts.split(' ')
  txt_msg = ''
  for _char in txt_chars:
  if _char != '00':
  txt_msg += chr(int(_char, 16))
  #print(txt_msg)

proc = subprocess.Popen(batt_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)

try:
 outs, errs = proc.communicate(timeout=10)
 res = str(outs, 'utf-8')
 #print(res)
 batt = int(res.split(':')[1].strip(), 16)
 txt_msg += " B={}".format(batt)
 print(txt_msg)
except subprocess.TimeoutExpired:
 proc.kill()
 outs, errs = proc.communicate()
 eres = str(outs, 'utf-8')
 #print(eres)
 batt = int(eres.split(':')[1].strip(), 16)
 txt_msg += " B={}".format(batt)
 print(txt_msg)

Heading

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

AD

AD

Heading

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

AD

AD

1 2 3 4 5 »