raspberry pi смс интернет

Дача, USB-модемы, две малины, или сказ о том, как я температуру в доме проверял.

Добрый день! Хочу рассказать вам про свои приключения и поиски надежного решения для удаленного мониторинга температуры помещения, наблюдения за окружающим миром и включения/выключения устройств.

Надо сказать, что устройства получились на удивление надежными и на данный момент отработали по пол года, без единого разрыва сбоя.

Дано: 2 дачи.

Первая - с газовым отоплением, и основная задача - поймать момент снижения температуры (ака потухший фитиль), чтобы осталось время приехать и зажечь его, не дать трубам разорваться от замерзшей в них воды. Интернет - gprs, качество приема - устойчивое.

Вторая - без отопления, только электрические тены. Тут необходимо удаленное включение устройств(тенов), поддержание комфортной температуры для сна. Интернет - отсутствует, gsm сигнал есть, однако работает скверно.

Так получилось, что у меня дома завалялась малинка и usb gprs свисток. Решил начать со второй дачи, дабы интеграцию с web сервисами оставить на потом.

Общение с внешним миром из-за отсутствия Интернет - только по смс.

Основная последовательность действий:

1) установка debian os

2) изменение modeswitch usb свистка, на режим модема

3) написание программы для работы с приемом, парсингом и отправкой сообщений.

Язык python, библиотека для общения с модемом - gammu, датчик температуры bmp085, LCD дисплей, и два простых реле.

Основные функции: Включение питания (пин 4), Включение второго устройства (пин 17), получение сведений о температуре и их отправка, переход в режим поддержания температуры в определенном интервале.

Самое интересное, код:

# -*- coding: utf-8 -*-
import gammu
import time
import RPi.GPIO as GPIO
import Adafruit_BMP.BMP085 as BMP085
import lcddriver
import os
from datetime import datetime
from subprocess import call


f = open('/var/log/sms','a')
f.write(str(datetime.now()) + ' System started\n')
f.close()

GPIO.setmode(GPIO.BCM)
pinList = [4, 17]
sensor = BMP085.BMP085()
lcd = lcddriver.lcd()

#Обьявляем телефоны, с которых мы будем обрабатывать смски
cellphones = ['+7926XXXXX','+7926XXXXXX']
currcommand = ''

for i in pinList: 
    GPIO.setup(i, GPIO.OUT) 
    GPIO.output(i, GPIO.HIGH)


sm = gammu.StateMachine()
sm.ReadConfig()
sm.Init()
sm.GetSMSStatus()

#Создаем функцую для удаления всех смс, на случай, если аппарат был выключен и накопилась очередь сообщений.

def delete_all_sms():
	status = sm.GetSMSStatus()
	remain = status['SIMUsed'] + status['PhoneUsed'] + status['TemplatesUsed']
	start = True
	while remain > 0:
		sms = sm.GetNextSMS(Start = True, Folder = 0)
		remain = remain - len(sms)
		for m in sms:
			sm.DeleteSMS(Location = m['Location'], Folder = 0)

#функция чтения смс, с удалением после прочтения.
def retSMS():
	start = True	
	sms=[{'Number':0,'Text':2},{'Number':0,'Text':2}]
	while 1:
		try :
			if start:
				sms = sm.GetNextSMS(Start = True, Folder=0)
				start = False
			else:
				sms = sm.GetNextSMS(Location = sms[0]['Location'], Folder=0)
		except gammu.ERR_EMPTY:
			break
		
	try:
		
		delete_all_sms()
	except gammu.ERR_EMPTY:
		a=1
	return(sms[0]['Number'],sms[0]['Text'])	

#Объявляем функцию отправки сообщений, с перезагрузкой, в случае сбоя. Такое случается крайне редко
# Однако, т.к. система находится далеко, необходимо, чтобы в случае падений, перезапускалось само.

def sndSMS(number,smstext):
	message = {
	'Text': smstext,
	'SMSC': {'Location': 1},
	'Number': number,
	}
	try:
		sm.SendSMS(message)
	except gammu.ERR_UNKNOWN:
		f = open('/var/log/sms','a')
		f.write(str(datetime.now()) + ' Failed to send sms\n')
		f.write(str(datetime.now()) + ' Rebooting in 3.5 minutes...\n')
		print ("failed to send")
		time.sleep(200)
		f.write(str(datetime.now()) + ' Rebooting...\n')
		f.close()
		os.system("sudo shutdown -r now")

	
#read temperature
def readtemp():
	curtemp=sensor.read_temperature()
	return curtemp


#Основная функция расшифровки сообщений, обработки заданий.
def parscom(detSms):
	currcommand=''
	if detSms[0] in cellphones:
			if detSms[1]=='On':
				GPIO.output(4, GPIO.LOW)
				sndSMS(detSms[0], 'Otoplenie on')
				currcommand='On'
			if detSms[1]=='Poliv':
				GPIO.output(17, GPIO.LOW)
				sndSMS(detSms[0], 'Poliv ON')
				currcommand='PolivOn'
			if detSms[1]=='PolivOff':
				GPIO.output(17, GPIO.HIGH)
				sndSMS(detSms[0], 'Poliv Otkluchen')
				currcommand='PolivOff'	
			if detSms[1]=='Off':
				GPIO.output(4, GPIO.HIGH)
				sndSMS(detSms[0], 'Otoplenie Off')
				currcommand='Off'
			if detSms[1]=='Temp':
				print readtemp()
				sndSMS(detSms[0], 'Temp: ' + str(readtemp()))
			if detSms[1].split()[0]=='Set':
				temp=detSms[1].split()[1]
				GPIO.output(4, GPIO.LOW)
				currcommand='Set ' + temp
				sndSMS(detSms[0], 'Night mode On. Temperature set: ' + str(temp))
	return currcommand

#Реализация функции поддержания температуры.
def otoplenie_night(settemp):
	curtemp=readtemp()
	try:
		if curtemp>int(settemp)+0.5:
			
			GPIO.output(4, GPIO.HIGH)
		if curtemp
			
			GPIO.output(4, GPIO.LOW)
	except:
		GPIO.output(4, GPIO.HIGH)


#Основной цикл - отправка смс при включении, вызов функций чтения смс, парсинга, и вывода на lcd дисплей.
sndSMS('+7926XXXXXX', 'Cucmema Pa6omaem')			
while 1:
	detSms=retSMS()
	newcommand = parscom(detSms)
	lcd.lcd_display_string("TEMnEPATYPA: " + str(readtemp()) + " C" , 1)
	if currcommand != newcommand and newcommand != '':
		currcommand=newcommand
		lcd.lcd_display_string("KOMAHDA:       " , 2)	
	lcd.lcd_display_string("KOMAHDA: " + currcommand  , 2)	
	try:
		if currcommand.split()[0]=='Set':
			otoplenie_night(currcommand.split()[1])
		
	except IndexError:
		a=0
	time.sleep(5)

	

После окончания работы над первым устройством экстренно закупил вторую малину, нашел второй свисток и начал ваять устройство для первой дачи. Благодаря наличию хорошего интернета, отсутсвия необходимости включать реле концепция немного изменилась, но работает так же надежно.

Работает по крону 2 скритпа:

1) делаем фото окружающей природы с камеры подключенной по usb к малине и отправляем на список почтовых адресов.

2) вызываем бесплатный интернет-сервис по отправке смс сообщений.

+ Запускается gammu демон, который автоматически подключается к интернету при загрузке малины.

Код получения картинки и отправки по почте:


from smtplib import SMTP_SSL
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email import Encoders
import os


#Меряем температуру (Датчик DS18B20)
def readtemp():
    tfile=open("/sys/bus/w1/devices/28-00000633a133/w1_slave")
    ttext=tfile.read()
    tfile.close()
    temp=ttext.split("\n")[1].split(" ")[9]
    temperature=float(temp[2:])/1000
    return temperature

temperatur=str(readtemp())


#Делаем фото
os.system ("fswebcam -r 1024x768 -S 15 /home/pi/pics/static/temp.jpg")

#Путь для аттача
filepath = "/home/pi/pics/static/temp.jpg"
basename = os.path.basename(filepath)
#куда отправлять письма:
address = ['XXX@gmail.com','XXXX@list.ru','XXX@mail.ru']

Наш аккаунт, откуда отправляем
adressfrom='XXX@yandex.ru'
# Compose attachment
part = MIMEBase('application', "octet-stream")
part.set_payload(open(filepath,"rb").read() )
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % basename)

# Compose message
msg = MIMEMultipart()
msg['From'] = adressfrom
msg['To'] =  ", ".join(address) 
msg['Subject'] = 'A vot i temperatura ' +  temperatur
msg['Body']='Temperatura' 
msg.attach(part)


# Send mail
smtp = SMTP_SSL()
smtp.connect('smtp.yandex.ru')
smtp.login(adressfrom, 'PASSWORD')
smtp.sendmail(adressfrom, address, msg.as_string())
smtp.quit()

В результате получаем на почту такую красивую картинку, и на душе как-то становится теплее.

А это код отправки СМС с использованием бесплатного веб-сервиса:


import requests
import os

#Читаем температуру
def readtemp():
    tfile=open("/sys/bus/w1/devices/28-00000633a133/w1_slave")
    ttext=tfile.read()
    tfile.close()
    temp=ttext.split("\n")[1].split(" ")[9]
    temperature=float(temp[2:])/1000
    return temperature

temperatur=str(readtemp())
#вызываем веб сервис, для формирования смс.
r = requests.get('http://sms.ru/sms/send?api_id=ID_API&to=7926NUMBER4&text=Temperatura+'+ temperatur)
q = requests.get('http://sms.ru/sms/send?api_id=ID_API&to=7910NUMBER&text=Temperatura+'+ temperatur)

Вскоре обнаружились сбои, связанные с зависанием малины после нескольких дней работы, несмотря на работу вотчдогов. Победил это просто, ежедневным ребутом. И, как я писал выше, с тех пор обе системы работают без нареканий. За прошедшую зиму благодаря системе удалось дважды спасти отопление дачи, вовремя получив заветную смс.

Спасибо за прочтение статьи! Некоторые детали я пропустил в своем повествовании, но готов ответить на любые возникшие вопросы :)

Тэги:

 

Автор:

Комментариев: 8

  • alfacom
    28.04.2016 в 10:00 ответ

    У меня небольшая куча вопросов. Фото природы — просто природа на даче красивая?) Код Питоновский? Многие популярные LCD-дисплеи поддерживают кириллические символы. Ваш не поддерживал, или лень возиться было? сбои связанные с зависанием малины Очень интересно. Какую малинку(и) использовали? Зависания были на обоих малинках? код отправки СМС используя бесплатный веб сервис Сразу подумал о sms.ru. Прочел код и убедился в своем предположении)

    • Rampage4
      28.04.2016 в 10:17 ответ

      Фото, да насамом деле просто мониторить, что стекла в доме не разбили, соседи приехали/уехали :) Код да, все на питоне. Очень простой и понятный для понимания язык. После увлечения малинкой, начал даже на работе его продвигать. Про Lcd — да, просто не хотелось убивать времени больше, чем было необходимо для конкретных задач. Очень интересно. Какую малинку(и) использовали? Зависания были на обоих малинках? Raspberry PI Model B. Да висли обе, причем с некоторой зависмостью от зоны приема gsm. Запускаю для теста дома (москва) — неделю работает без проблем. На даче — через три дня уходит «в себя». Сразу подумал о sms.ru. Прочел код и убедился в своем предположении) Реально, очень крутой сервис, учитывая бесплатность для разработчиков. Работает без сбоев пол года.

  • amf
    19.05.2016 в 15:50 ответ

    Очень интересно почитать. спасибо! Подскажите, почему было решено делать на Raspberry? Первый проект (да и второй тоже) точно бюджетнее было сделать на Arduino.

    • Rampage4
      19.05.2016 в 16:24 ответ

      Бюджетнее ли при наличии usb модемов? :-) При оценке вариантов, конечно смотрел на трудоемкость и стоимость. Трудоемкость для меня победила малина: возможность использования Python, и наличия полноценной OS. Стоимость: смотрел на стоимость GSM шилдов в поднебесной… и видел ценники за 600+ рублей. Малину(вторую) взял за 1к рублей «с рук». Потому получилось по вполне адекватной цене, и дешевле gsm розеток :-)

      • amf
        19.05.2016 в 21:04 ответ

        Спасибо за ответ. да, видимо, возможность использования usb модемов — это серьезный плюс в копилку малины. Прямо да, реально. Да еще и вторая малина за дешево )) тоже хочу что-то подобное сделать, смотрел в сторону Arduino + какой-нить GSM-модуль типа m590e. из китая, естественно. И там пока бюджет всего в 1к. ))

        • Rampage4
          19.05.2016 в 22:06 ответ

          Ну, вместо малины оранж пи ван можно взять. Одноплатник за 9.99 usd. Я вот в конкурсе третью не выиграл… пришлось оранж взять :))) уже доставили… начинаю теперь новые экспиременты на нем. Ардуину, кстати про мини можешь взять. 1.45usd стоит в забугорье. Только ножки припаять надо будет и усб уарт переходник для записи скетчей.

          • amf
            20.05.2016 в 10:50 ответ

            orange pi — интересная штука. ) надо будет попробовать. сначала я тоже на про мини смотрел, но потом «открыл» nano. цена чуть больше, но и паять не надо, и программировать проще. и разъем знакомый.

  • vdk10
    22.11.2017 в 15:41 ответ

    Замечательно!Есть несколько вопросов:1)  Какие настройки у модемов для работы через gammu? Т.е. покажите настройки/конфиг файл gammu для первой дачи.Пакет gammu был предварительно установлен?2) Можно подробнее что делалось с помощью modeswitch?

Ваш комментарий

Авторизуйтесь для отправки комментария

© Сообщество пользователей RaspberryPi 2021