📜 ⬆️ ⬇️

Smart greenhouse in Telegram

Good day. On our plot there is a greenhouse. Its main problem is overheating in hot weather, because designed primarily for the Siberian spring. The only way out is to constantly open / close doors and windows in order to maintain the temperature. But this is not always possible. And if this is not done, then the temperature rises to +50 degrees, which is clearly not good. In the evening everything can be frozen. And so began its automation.

image

First of all, we bought the Raspberry Pi 2. Having dealt with it, we connected the DS18B20 sensor for this article . Then two second-hand car windows were bought. Like all DC motors, they move according to polarity. Therefore, we connect two relays to each engine: one for opening, the other for closing. These relays are already connected through transistors to the GPIO ports themselves. And we feed this whole thing with a 12V battery. Also, in order not to burn the engines, limit switches were installed in the extreme positions of the window, and if the window was opened / closed, the network was completely torn.

image
')
image

And for communication, we use a TP-LINK WiFi adapter with an enhanced Dual Square antenna for confident reception of a neighbor's WIFI home WIFI router, which is 40 meters away.

image

Now we are writing a program to control these drives. Python language was chosen, since it has normal support for Raspberry Pi and specifically GPIO ports. In order to open the window, we need to apply + 3.3V to the transistor, which activates the relay, and then it will start to open the window. To close it, we do the same, only in this case, our relay is connected opposite to the drive. But on the Raspberry, we just supply current to one port, then to another. We decided that if the temperature is greater than 26 we open the window within 1 second. Then wait 3 minutes. If it's hot again, then open the second window for a second. Waiting again for 3 minutes, and doing it again. The same with the closure, only here the temperature should be below 24 degrees. And here is the code:

temp.py
import RPi.GPIO as GPIO import time import os import datetime GPIO.setmode(GPIO.BOARD) GPIO.cleanup() GPIO.setup(31, GPIO.OUT) GPIO.setup(33, GPIO.OUT) GPIO.setup(35, GPIO.OUT) GPIO.setup(37, GPIO.OUT) #  def gettemp(): if os.path.isdir("id "): #  ,    tfile2=open("/sys/bus/w1/devices/id ") ttext2=tfile2.read() tfile2.close() temp2=ttext2.split("\n")[1].split(" ")[9] t2=float(temp2[2:])/1000 print t2 else: # ,    print ('File not found') t2==24 return t2 t2=24 #     while True:   t2=gettemp() if t2<24: #   24,       GPIO.output(37, 1) print ("close1") time.sleep(1) GPIO.output(37, 0) elif t2>26: #  26,       GPIO.output(35, 1) print ("open1") time.sleep(2) GPIO.output(35, 0) else: #    print ("none1") time.sleep(180)# 3  #   t2=gettemp() #   ,    . if t2<24: GPIO.output(33, 1) print ("close2") time.sleep(1) GPIO.output(33, 0) elif t2>26: GPIO.output(31, 1) print ("open2") time.sleep(1) GPIO.output(31, 0) else: print ("none2") #  3  time.sleep(180) 



And now the show begins for those who are not interested in physics.

Having installed Apache on the Raspbian distribution, for a month we could not reach the page from the Internet. That just did not do. We set up ports, opened them, nothing helped. And in the local network, everything worked. Then we learned the sad truth: we are behind NAT. And our operator does not provide services on a dedicated IP (Hello to Telecom Region employees). Took over a lot of workarounds, but nothing came of it. I tried to make a web interface on a hosting, but I also need an IP to synchronize the database. The IPv6 broker has already closed by then. And it is expensive to make VPN, because you want everything for free. And then they decided to use Telegram bot. As it turned out, it has two modes: constant polling the server and sending messages directly to us. The first option came up, because does not require an IP address from us. Having rummaged on the Internet found library: pytelegrambotapi. And he began to write the code. True, there were problems. MySQL's barely found library refused to write to the database, but at that it read everything is fine from it. I had to make a crutch: transfer data to a file stored in RAM, then run a bash script that reads the data and writes it to the database.

Make the file config.ini, throw there:

 [mysql] host = localhost database = telegram user = root password = secret 

Do not forget to replace the data with your own.

Create a python_mysql_dbconfig.py file with the following contents:

 from configparser import ConfigParser def read_db_config(filename='config.ini', section='mysql'): """ Read database configuration file and return a dictionary object :param filename: name of the configuration file :param section: section of database configuration :return: a dictionary of database parameters """ # create parser and read ini configuration file parser = ConfigParser() parser.read(filename) # get section, default to mysql db = {} if parser.has_section(section): items = parser.items(section) for item in items: db[item[0]] = item[1] else: raise Exception('{0} not found in the {1} file'.format(section, filename)) return db 

We also need to create the file python_mysql_connect2.py, with the following content:

 from mysql.connector import MySQLConnection, Error from python_mysql_dbconfig import read_db_config def connect(): """ Connect to MySQL database """ db_config = read_db_config() try: print('Connecting to MySQL database...') conn = MySQLConnection(**db_config) if conn.is_connected(): print('connection established.') else: print('connection failed.') except Error as error: print(error) finally: conn.close() print('Connection closed.') if __name__ == '__main__': connect() 

Now we have prepared everything for working with the database.

Let us digress a little from the database and proceed directly to communicating with the bot. Well, as usual, we write @BotFather, and take a token from it. Create a file config.py, and write two lines to it:

 # -*- coding: utf-8 -*- token = ' ' 

I decided to implement three functions in the bot:


With the first one everything is simple, upon request we read the file with the temperature, and send it to the user.

With pictures more difficult. I use the Motion utility. In its parameters, ask to put the images in the folder in the RAM, well, let's say every 30 seconds. And we make files with the same name, and they just replace each other. And then, upon request, send the file to the user.

Well, the third, the most difficult module: window management. My main task is for the automation to work, but if necessary, we can disable it. I did it like this. Created another file in RAM. When we send a request for opening / closing, opening a window, closing a window or turning the automation on / off, the bot writes the command number to this file. Every five seconds, the window manager reads this file, and if it recognizes the command, executes it. After the execution of the same file writes that everything went well. The bot reads the file again, and notifies us that the command is completed.

Well, now the source code. First, the same program for opening windows, only already converted for a bot (temp.py):

temp.py
 import RPi.GPIO as GPIO import time import os import datetime GPIO.setmode(GPIO.BOARD) GPIO.cleanup() GPIO.setup(31, GPIO.OUT) GPIO.setup(33, GPIO.OUT) GPIO.setup(35, GPIO.OUT) GPIO.setup(37, GPIO.OUT) #  ,     f = open('/mnt/raw/wind', 'w') f.write('OK') f.close() #,    f = open('/mnt/raw/pos', 'w') f.write('1') f.close() #  def gettemp(): if os.path.isdir("/sys/bus/w1/devices/id "): #  ,    tfile2=open("/sys/bus/w1/devices/id /w1_slave") ttext2=tfile2.read() tfile2.close() temp2=ttext2.split("\n")[1].split(" ")[9] t2=float(temp2[2:])/1000 print t2 else: # ,    print ('File not found') t2==24 return t2 #    i=1 #  t2=24 #    def info(): f = open('/mnt/raw/wind') com = f.read() f.close() return com # ,    def ans(): f = open('/mnt/raw/wind', 'w') f.write('OK') f.close() print ("OK") #  def rob(): c = info() if c=="10": GPIO.output(37, 1) print ("close1") time.sleep(3) GPIO.output(37, 0) ans() elif c=="11": GPIO.output(35, 1) print ("open1") time.sleep(2) GPIO.output(35, 0) ans() elif c=="12": GPIO.output(37, 1) print ("close1") time.sleep(3) GPIO.output(37, 0) ans() elif c=="13": GPIO.output(35, 1) print ("open1") time.sleep(1) GPIO.output(35, 0) ans() elif c=="20": GPIO.output(33, 1) print ("close2") time.sleep(3) GPIO.output(33, 0) ans() elif c=="21": GPIO.output(31, 1) print ("open2") time.sleep(3) GPIO.output(31, 0) ans() elif c=="22": GPIO.output(33, 1) print ("close2") time.sleep(1) GPIO.output(33, 0) ans() elif c=="23": GPIO.output(31, 1) print ("open2") time.sleep(1) GPIO.output(31, 0) ans() elif c=="30": global i i=0 ans() f = open('/mnt/raw/pos', 'w') f.write('0') f.close() print('30') global i i=0 ans() elif c=="31": f = open('/mnt/raw/pos', 'w') f.write('1') f.close() print('31') global i i=1 ans() while True: #    rob() #,    if i==1: gettemp() if t2<24: GPIO.output(37, 1) print ("close1") time.sleep(1) GPIO.output(37, 0) elif t2>26: GPIO.output(35, 1) print ("open1") time.sleep(2) GPIO.output(35, 0) else: print ("none1") # 3 ,        j=0 while(j<36): rob() time.sleep(5) j=j+1 if i==0: break gettemp() if t2<24: GPIO.output(33, 1) print ("close2") time.sleep(1) GPIO.output(33, 0) elif t2>26: GPIO.output(31, 1) print ("open2") time.sleep(1) GPIO.output(31, 0) else: print ("none2") j=0 while(j<36): rob() time.sleep(5) j=j+1 if i==0: break 



But now let's talk about the bot itself. As I said, I use the PyTelegramBotApi library. If you refer to the documentation on GitHub , then you can understand that the bot uses handlers for processing commands. A handler is an event in our program that defines an action. In our case, this is a specific phrase in the message. And the action is all we can do in the python language. In this case, we will send the user some information to the user or write commands for windows to a file. Basically, our program consists of these very handles and server polling commands.

But I also wrote and added another interesting thing myself: an authorization block. Well, as the name implies, it is made to protect our greenhouse from unauthorized access. It works simply. When you first connect to the bot, he asks us for a password. If we enter it correctly, the bot adds us to the database, and with the following connections, we do not need to authorize. The bot recognizes us with chat-id. Chat-id of the last user is stored in a variable, so as not to pull the base all the time.

Now we create the daba.py file and write this:

daba.py
 from mysql.connector import MySQLConnection, Error from python_mysql_dbconfig import read_db_config import time def getkey(): #    try: dbconfig = read_db_config() conn = MySQLConnection(**dbconfig) cursor = conn.cursor() cursor.execute("SELECT key2 FROM tkey where id=0") row = cursor.fetchone() return row print(row) except Error as e: print(e) finally: cursor.close() conn.close() def sendup(): #    ( ) stime=time.time() query = "INSERT INTO uptime(datetime, also) " \ "VALUES(now(), 20)" args=(stime) try: dbconfig = read_db_config() conn = MySQLConnection(**dbconfig) cursor = conn.cursor() cursor.execute(query) row = cursor.fetchone() return(row) print(row) except Error as e: print(e) finally: cursor.close() conn.close() def getid(idi): #   id    query="SELECT accecpt FROM users WHERE chatid ='"+str(idi)+"'" try: dbconfig = read_db_config() conn = MySQLConnection(**dbconfig) cursor = conn.cursor() cursor.execute(query) row = cursor.fetchone() #print (str(row)) if str(row)=="None": return 0; print (0) else: return 20; except Error as e: print(e) #finally: #cursor.close() #conn.close() def newuser(idi): #     query = ("INSERT INTO users SET `chatid`='12345'") try: dbconfig = read_db_config() conn = MySQLConnection(**dbconfig) cursor = conn.cursor() cursor.execute(query) row = cursor.fetchone() print(row) except Error as e: print(e) return(e) finally: cursor.close() conn.close() if __name__ == '__main__': query_with_fetchone() 



Also let's do some more auxiliary scripts right away. Create a file newuser.sh and write to it:

 #!/bin/bash a=`cat /mnt/raw/user` cat /dev/null > /mnt/raw/user mysql -u root -pkoshak << EOF use telegram; INSERT INTO users(chatid) VALUES('$a'); EOF 

And create two scripts to launch the bot and windows program:

 #!/bin/bash i=0 while [ $i = 0 ] do echo New python sleep 5 python3 bot.py done 

And one more:

 #!/bin/bash i=0 while [ $i = 0 ] do echo New python sleep 5 python3 temp.py done 

“Why are we doing this?” You ask. And here the fact is that sometimes due to an unstable Internet connection, or an error on the Telegram server, the program may crash. And the script drives it in an eternal cycle: it flew out - launched after 5 seconds again. And for windows I did it for every fireman: suddenly, too, because of a malfunction, the program will fly out, but we are not in the greenhouse, we will come back and we will have tomato soup or tomato ice cream.

Well, now the most important thing is the bot script itself:

bot.py
 # -*- coding: utf-8 -*- import config import telebot import subprocess import time from telebot import types import datetime import os from daba import getkey from daba import sendup from daba import getid #from daba import newuser #from temp import tep import os #  f = open('/mnt/raw/user', 'tw', encoding='utf-8') f.close() global par par=0 #    global a a="  .    /auth []" #   def get_temp(): if os.path.isdir("/sys/bus/w1/devices/id "): tfile2=open("/sys/bus/w1/devices/id /w1_slave") ttext2=tfile2.read() tfile2.close() temp2=ttext2.split("\n")[1].split(" ")[9] t2=float(temp2[2:])/1000 return t2 else: print ('File not found') # keyword=str(getkey())[2:-3] #  bot = telebot.TeleBot(config.token) print (sendup()) #   ######################### ########################################## markup2 = types.ReplyKeyboardMarkup(row_width=1, resize_keyboard=True) #, ,      markdown = types.ReplyKeyboardHide() # itembtn5 = types.KeyboardButton(' ') #  5 markup2.add(itembtn5) #    ######################### ########################################## #########################  ########################################## markup = types.ReplyKeyboardMarkup(row_width=3, resize_keyboard=True) #, ,      itembtn1 = types.KeyboardButton('  ') #  1 itembtn4 = types.KeyboardButton('  ') itembtn2 = types.KeyboardButton('  ') #  2 markup.add(itembtn1, itembtn4, itembtn2) #    #########################  ########################################## ######################### ########################################## markup3 = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True) #, ,      itembtn10 = types.KeyboardButton('   ') #  10 itembtn11 = types.KeyboardButton('️  ') itembtn12 = types.KeyboardButton(' ') markup3.add(itembtn10, itembtn11, itembtn12) #    markup4 = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True) #, ,      itembtn13 = types.KeyboardButton('   ') #  13 markup4.add(itembtn13, itembtn11, itembtn12) #    markup5 = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True) #, ,      itembtn14 = types.KeyboardButton('  ') #  14 itembtn15 = types.KeyboardButton('  ') #  15 itembtn16 = types.KeyboardButton('️ ') #  16 markup5.add(itembtn14, itembtn15, itembtn16) #    markup6 = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True) #, ,      itembtn17 = types.KeyboardButton('️   ') #  17 itembtn18 = types.KeyboardButton('️   ') #  18 itembtn19 = types.KeyboardButton('   ') #  19 itembtn20 = types.KeyboardButton('   ') # 20 itembtn21 = types.KeyboardButton('️ ') #  21 markup6.add(itembtn17, itembtn18, itembtn19, itembtn20, itembtn21) #    markup7 = types.ReplyKeyboardMarkup(row_width=2, resize_keyboard=True) #, ,      itembtn22 = types.KeyboardButton('️   ') #  22 itembtn23 = types.KeyboardButton('️   ') #  23 itembtn24 = types.KeyboardButton('   ') # 24 itembtn25 = types.KeyboardButton('   ') # 25 markup7.add(itembtn22, itembtn23, itembtn24, itembtn25, itembtn21) #    ######################### ########################################## bot.send_message(45215125, "")#   chat-id #    def pos(): f = open('/mnt/raw/pos') com = f.read() f.close() return com # def avtor(idi): global par#       if par==idi: return 0 else:#    ,    ,  0 if getid(str(idi))==20: par=idi#    return 0 else:#      bot.send_message(idi, "  .    /auth []", reply_markup=markup2) return 1 @bot.message_handler(regexp=" ") def auth(message): bot.send_message(message.chat.id, " /auth []") #  @bot.message_handler(commands=['auth']) def start2(message): if message.text[6:]==keyword:#    if getid(str(message.chat.id))==20:#    ,         20 bot.send_message(message.chat.id, "  ") else: global par bot.send_message(message.chat.id, "", reply_markup=markup) par=message.chat.id # chat-id    f = open('/mnt/raw/user', 'w') f.write(str(message.chat.id)) f.close() os.system('newuser.sh') print (message.chat.id) print (par) else: bot.send_message(message.chat.id, "") print (keyword) print (message.text[6:]) print (message.chat.id) #  /start @bot.message_handler(commands=['start']) def start(message): global par if avtor(message.chat.id)!=0: print (par) bot.send_message(message.chat.id, "   .    /auth []", reply_markup=markup2) else: bot.send_message(message.chat.id, "   .  /help,  ,    .") #   - /help @bot.message_handler(commands=['help']) def help(message): if avtor(message.chat.id)==0: mas='       . \n    ,    : \n   - /help \n       :)' bot.send_message(message.chat.id, mas, reply_markup=markup) print (message.chat.id, message.text) #      @bot.message_handler(commands=['show']) def show(message): if avtor(message.chat.id)==0: mas=' ' bot.send_message(message.chat.id, mas, reply_markup=markup) print (message.chat.id, message.text) #  @bot.message_handler(regexp="  ") def temp(message): if avtor(message.chat.id)==0: tp=get_temp() mas='   : '+str(tp)+'°C' bot.send_message(message.chat.id, mas) print (message.chat.id, message.text) #  @bot.message_handler(regexp="  ") def photo(message): if avtor(message.chat.id)==0: path='/mnt/raw/photo/foto.jpg' #     try: f = open(path, 'rb') #  -  bot.send_photo(message.chat.id, f) #  print (message.chat.id, message.text) except: bot.send_message(message.chat.id, "  :(") #    @bot.message_handler(regexp="  ") def windows(message): if avtor(message.chat.id)==0: print ("window") print (pos()) if str(pos())[0]=='1': bot.send_message(message.chat.id, "", reply_markup=markup3)#  ,      « » else: bot.send_message(message.chat.id, "", reply_markup=markup4)#      #  @bot.message_handler(regexp=" ") def windows(message): if avtor(message.chat.id)==0: bot.send_message(message.chat.id, "", reply_markup=markup) #  @bot.message_handler(regexp="   ") def windows(message): if avtor(message.chat.id)==0: f = open('/mnt/raw/wind', 'w')#  f.write('30')#   ,     30 f.close()#  k="No"#   while k[0:2]!="OK":#  time.sleep(5)# 5  f = open('/mnt/raw/wind')#  k = f.read()#  f.close()# print(k[0:2]) bot.send_message(message.chat.id, "", reply_markup=markup4) @bot.message_handler(regexp="   ") def windows(message): if avtor(message.chat.id)==0: f = open('/mnt/raw/wind', 'w') f.write('31') f.close() k="No" while k[0:2]!="OK": time.sleep(5) f = open('/mnt/raw/wind') k = f.read() f.close() print(k[0:2]) bot.send_message(message.chat.id, "", reply_markup=markup3) @bot.message_handler(regexp="️  ") def windows(message): if avtor(message.chat.id)==0: bot.send_message(message.chat.id, "", reply_markup=markup5) @bot.message_handler(regexp="️ ") def windows(message): if avtor(message.chat.id)==0: if str(pos())[0]=='1': bot.send_message(message.chat.id, "", reply_markup=markup3) else: bot.send_message(message.chat.id, "", reply_markup=markup4) @bot.message_handler(regexp="️ ") def windows(message): if avtor(message.chat.id)==0: bot.send_message(message.chat.id, "", reply_markup=markup5) #   @bot.message_handler(regexp="  ") def windows(message): if avtor(message.chat.id)==0: bot.send_message(message.chat.id, "", reply_markup=markup6) @bot.message_handler(regexp="  ") def windows(message): if avtor(message.chat.id)==0: bot.send_message(message.chat.id, "", reply_markup=markup7) @bot.message_handler(regexp="️   ") def windows(message): if avtor(message.chat.id)==0: f = open('/mnt/raw/wind', 'w') f.write('11') f.close() k="No" while k[0:2]!="OK": time.sleep(5) f = open('/mnt/raw/wind') k = f.read() f.close() print(k[0:2]) bot.send_message(message.chat.id, "", reply_markup=markup6) @bot.message_handler(regexp="️   ") def windows(message): if avtor(message.chat.id)==0: f = open('/mnt/raw/wind', 'w') f.write('10') f.close() k="No" while k[0:2]!="OK": time.sleep(5) f = open('/mnt/raw/wind') k = f.read() f.close() print(k[0:2]) bot.send_message(message.chat.id, "", reply_markup=markup6) @bot.message_handler(regexp="   ") def windows(message): if avtor(message.chat.id)==0: f = open('/mnt/raw/wind', 'w') f.write('13') f.close() k="No" while k[0:2]!="OK": time.sleep(5) f = open('/mnt/raw/wind') k = f.read() f.close() print(k[0:2]) bot.send_message(message.chat.id, "", reply_markup=markup6) @bot.message_handler(regexp="   ") def windows(message): if avtor(message.chat.id)==0: f = open('/mnt/raw/wind', 'w') f.write('12') f.close() k="No" while k[0:2]!="OK": time.sleep(5) f = open('/mnt/raw/wind') k = f.read() f.close() print(k[0:2]) bot.send_message(message.chat.id, "", reply_markup=markup6) @bot.message_handler(regexp="️   ") def windows(message): if avtor(message.chat.id)==0: f = open('/mnt/raw/wind', 'w') f.write('21') f.close() k="No" while k[0:2]!="OK": time.sleep(5) f = open('/mnt/raw/wind') k = f.read() f.close() print(k[0:2]) bot.send_message(message.chat.id, "", reply_markup=markup7) @bot.message_handler(regexp="️   ") def windows(message): if avtor(message.chat.id)==0: f = open('/mnt/raw/wind', 'w') f.write('20') f.close() k="No" while k[0:2]!="OK": time.sleep(5) f = open('/mnt/raw/wind') k = f.read() f.close() print(k[0:2]) bot.send_message(message.chat.id, "", reply_markup=markup7) @bot.message_handler(regexp="   ") def windows(message): if avtor(message.chat.id)==0: f = open('/mnt/raw/wind', 'w') f.write('23') f.close() k="No" while k[0:2]!="OK": time.sleep(5) f = open('/mnt/raw/wind') k = f.read() f.close() print(k[0:2]) bot.send_message(message.chat.id, "", reply_markup=markup7) @bot.message_handler(regexp="   ") def windows(message): if avtor(message.chat.id)==0: f = open('/mnt/raw/wind', 'w') f.write('22') f.close() k="No" while k[0:2]!="OK": time.sleep(5) f = open('/mnt/raw/wind') k = f.read() f.close() print(k[0:2]) bot.send_message(message.chat.id, "", reply_markup=markup7) #  ,    @bot.message_handler(content_types=["text"]) def repeat_all_messages(message): if avtor(message.chat.id)==0: bot.send_message(message.chat.id, "    .  /help,    ") print (message.chat.id, message.text) #      if __name__ == '__main__': bot.polling() 




Do not forget to specify here the sensor id, chat-id and the path to the partition in RAM. Now we have almost everything ready. We download this dump , and upload the database to our server, and do not forget to mount the partition in RAM, I think 10 MB is enough. We launch our two starter scripts and rejoice. The default password is telbot. Change it in the table tkey database.

SMS informing


Also did SMS informing in case of overheating. Create the sms.py file:

sms.py
 #!/usr/bin/env python # -*- coding: utf8 -*- """   .. t_aleksandr_v@inbox.ru 17.02.2015 """ """        sms.ru """ """   :""" """ -i  --idsender - id   sms.ru""" """ -t  --to -      79219996660""" """ -s  --subject -    """ from urllib2 import urlopen from optparse import OptionParser def sendsms(idsender,subject,to): subject = subject.replace(" ","+") url="http://sms.ru/sms/send?api_id=%s&text=%s&to=%s" %(idsender,subject,to) res=urlopen(url) if __name__ == '__main__': parser = OptionParser() parser.add_option("-i", "-- ", dest="idsender", default=" ", help="ID user on sms.ru", metavar="IDSENDER") parser.add_option("-t", "-- ", dest="to", default=" ", help="to telephone number", metavar="TO") parser.add_option("-s", "--temperatyra 32", dest="subject", default="Jara tut, otkroy okno", help="Name of subject", metavar="SUBJECT") (options, args) = parser.parse_args() sendsms(options.idsender,options.subject,options.to) 




We register on sms.ru and take an API-key there in the section for programmers. Just do not forget to specify your phone number in the script.

:

 Vr=0 

:

 d = datetime.today() V = d.strftime('%H') V = int(V) if (t2>32 and Vr!=V): print (V) Vr=V os.system('/home/samba/sms.py') 

32, , .

PS .

, .

Source: https://habr.com/ru/post/400499/


All Articles