4003| 7
|
[项目] 【智控万物】微信QQ邮件温度计 |
本帖最后由 云天 于 2021-1-26 20:51 编辑 【项目设计】 可通过微信直接看到家里的室温,不用打开微信小程序或其它APP。使用Mind+中 Python 模式“PinPong库”。 【PinPong库】 PinPong库是一套控制开源硬件主控板的Pyhton库,基于Firmata协议并兼容MicroPython语法,5分钟即可让你上手使用Python控制开源硬件。 借助于PinPong库,直接用Python代码就能给各种常见的开源硬件编程。其原理是给开源硬件烧录一个特定的固件,使开源硬件可以通过串口与电脑通讯,执行各种命令。 PinPong库的名称由“Pin”和“Pong”组成,“Pin”指引脚,“PinPong”为“乒乓球”的谐音,指信号的往复。 pinpong库的设计,是为了让开发者在开发过程中不用被繁杂的硬件型号束缚,而将重点转移到软件的实现。哪怕程序编写初期用Arduino开发,部署时改成了掌控板,只要修改一下硬件的参数就能正常运行,实现了“一次编写处处运行”。 【Mind+ Python模式】
http://mindplus.cc/ 【开启POP3/SMTP服务】 因要向QQ邮箱发送邮件,所以要设置自己的QQ邮箱开启POP3/SMTP服务,同时通过手机发送验证短信,生成授权码。 Forgotten补充设置过程图片 【微信开启QQ邮箱提醒】 https://kf.qq.com/touch/faq/1506 ... Uz.html?platform=14 【硬件】 主控板使用Arduino uno,温度传感器为:LM35线性模拟温度传感器 连接示意图 【代码编写】 #!/usr/bin/python # -*- coding: UTF-8 -*- import smtplib from email.mime.text import MIMEText from email.utils import formataddr import time from pinpong.board import Board,Pin,ADC Board("uno").begin() adc0 = Pin(Pin.A0, Pin.ANALOG) my_sender='********@qq.com' # 发件人邮箱账号 my_pass = 'syzwyzj***xuqbgbi' # 发件人邮箱密码(授权码) my_user='*******@qq.com' # 收件人邮箱账号,我这边发送给自己 def mail(Form,Form_name,Password,To,To_name,Title,Content): ret=True try: msg=MIMEText(Title,'plain','utf-8') msg['From']=formataddr([Form_name,Form]) # 括号里的对应发件人邮箱昵称、发件人邮箱账号 msg['To']=formataddr([To_name,To]) # 括号里的对应收件人邮箱昵称、收件人邮箱账号 msg['Subject']=Content # 邮件的主题,也可以说是标题 server=smtplib.SMTP_SSL("smtp.qq.com", 465) # 发件人邮箱中的SMTP服务器,端口是25 server.login(Form, Password) # 括号中对应的是发件人邮箱账号、邮箱密码 server.sendmail(Form,[To,],msg.as_string()) # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件 server.quit() # 关闭连接 except Exception: # 如果 try 中的语句没有执行,则会执行下面的 ret=False ret=False return ret while True: v = adc0.read_analog() tem = round(v*(5/10.24),1) print(tem) ret=mail(my_sender,"QQ邮件温度计",my_pass,my_user,"温度","当前室内温度为",str(tem)+"℃") if ret: print("邮件发送成功") else: print("邮件发送失败") time.sleep(60) 【邮件协议】 发送邮件——SMTP协议 SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。SMTP协议属于TCP/IP协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。通过SMTP协议所指定的服务器,就可以把E-mail寄到收信人的服务器上了,只要几分钟。 接收邮件——POP3和IMAP POP是指邮局协议,目的是让用户可以访问邮箱服务器中的邮件,允许用户从服务器上把邮件存储到本地主机(即自己的计算机)上,同时删除保存在邮件服务器上的邮件,而POP3服务器则是遵循POP3协议的接收邮件服务器,用来接收电子邮件的。 后来又出现了IMAP协议(Interactive Mail Access Protocol),即交互式邮件访问协议,与POP3的不同在于:开启了IMAP后,在电子邮件客户端收取的邮件仍然保留在服务器上,同时在客户端上的操作都会反馈到服务器上,如:删除邮件,标记已读等,服务器上的邮件也会做相应的动作。 【发送邮件,获取室内温度】 以下代码实现,每60秒测试一次邮箱中是否有主题为“温度”的邮件。如果有,发送当前温度到邮箱。 #!/usr/bin/python # -*- coding: UTF-8 -*- import poplib import datetime from email.parser import Parser from email.header import decode_header from email.utils import parseaddr import smtplib from email.mime.text import MIMEText from email.utils import formataddr import time from pinpong.board import Board,Pin,ADC Board("uno").begin() adc0 = Pin(Pin.A0, Pin.ANALOG) my_sender='********@qq.com' # 发件人邮箱账号 my_pass = 'syzwy*****qbgbi' # 发件人邮箱密码(授权码) my_user='*********@qq.com' # 收件人邮箱账号,我这边发送给自己 # 此函数通过使用poplib实现接收邮件 def recv_email_by_pop3(QQ_Address,Password): # 要进行邮件接收的邮箱。改成自己的邮箱 email_address = QQ_Address # 要进行邮件接收的邮箱的密码。改成自己的邮箱的密码 # 设置 -> 账户 -> POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 -> 开启服务:POP3/SMTP服务 # 设置 -> 账户 -> POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 -> 生成授权码 email_password = Password # 邮箱对应的pop服务器,也可以直接是IP地址 # 改成自己邮箱的pop服务器;qq邮箱不需要修改此值 pop_server_host = "pop.qq.com" # 邮箱对应的pop服务器的监听端口。改成自己邮箱的pop服务器的端口;qq邮箱不需要修改此值 pop_server_port = 995 try: # 连接pop服务器。如果没有使用SSL,将POP3_SSL()改成POP3()即可其他都不需要做改动 email_server = poplib.POP3_SSL(host=pop_server_host, port=pop_server_port, timeout=10) print("pop3----connect server success, now will check username") except: print("pop3----sorry the given email server address connect time out") exit(1) try: # 验证邮箱是否存在 email_server.user(email_address) print("pop3----username exist, now will check password") except: print("pop3----sorry the given email address seem do not exist") exit(1) try: # 验证邮箱密码是否正确 email_server.pass_(email_password) print("pop3----password correct,now will list email") except: print("pop3----sorry the given username seem do not correct") exit(1) # 邮箱中其收到的邮件的数量 email_count = len(email_server.list()[1]) # list()返回所有邮件的编号: resp, mails, octets = email_server.list() # 遍历所有的邮件 if len(mails)>0 : #for i in range(1, len(mails) + 1):#这里只读最新收到的邮件 # 通过retr(index)读取第index封邮件的内容;这里读取最后一封,也即最新收到的那一封邮件 resp, lines, octets = email_server.retr(len(mails)) # lines是邮件内容,列表形式使用join拼成一个byte变量 email_content = b'\r\n'.join(lines) try: # 再将邮件内容由byte转成str类型 email_content = email_content.decode('utf-8') except Exception as e: print(str(e)) # # 将str类型转换成<class 'email.message.Message'> # msg = email.message_from_string(email_content) msg = Parser().parsestr(email_content) return(parse_email(msg, 0)) # 关闭连接 email_server.close() def parse_email(msg, indent): if indent == 0: # 邮件的From, To, Subject存在于根对象上: for header in ['From', 'To', 'Subject']: value = msg.get(header, '') if value: if header=='Subject': # 需要解码Subject字符串: value = decode_str(value) print(value) return value else: # 需要解码Email地址: hdr, addr = parseaddr(value) name = decode_str(hdr) value = u'%s <%s>' % (name, addr) #print('%s%s: %s' % (' ' * indent, header, value)) # 解码 def decode_str(s): value, charset = decode_header(s)[0] if charset: value = value.decode(charset) return value # 猜测字符编码 def guess_charset(msg): # 先从msg对象获取编码: charset = msg.get_charset() if charset is None: # 如果获取不到,再从Content-Type字段获取: content_type = msg.get('Content-Type', '').lower() for item in content_type.split(';'): item = item.strip() if item.startswith('charset'): charset = item.split('=')[1] break return charset def mail(Form,Form_name,Password,To,To_name,Title,Content): ret=True try: msg=MIMEText(Title,'plain','utf-8') msg['From']=formataddr([Form_name,Form]) # 括号里的对应发件人邮箱昵称、发件人邮箱账号 msg['To']=formataddr([To_name,To]) # 括号里的对应收件人邮箱昵称、收件人邮箱账号 msg['Subject']=Content # 邮件的主题,也可以说是标题 server=smtplib.SMTP_SSL("smtp.qq.com", 465) # 发件人邮箱中的SMTP服务器,端口是25 server.login(Form, Password) # 括号中对应的是发件人邮箱账号、邮箱密码 server.sendmail(Form,[To,],msg.as_string()) # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件 server.quit() # 关闭连接 except Exception: # 如果 try 中的语句没有执行,则会执行下面的 ret=False ret=False return ret while True: if recv_email_by_pop3(my_sender,my_pass)=="温度": v = adc0.read_analog() tem = round(v*(5/10.24),1) print(tem) ret=mail(my_sender,"QQ邮件温度计",my_pass,my_user,"温度","当前室内温度为",str(tem)+"℃") if ret: print("邮件发送成功") else: print("邮件发送失败") time.sleep(60) |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed