大数跨境
0
0

用Mind+中 Python 模式“PinPong库”制作一个微信QQ邮件温度计

用Mind+中 Python 模式“PinPong库”制作一个微信QQ邮件温度计 蘑菇云创造
2021-01-28
3
导读:【智控万物】微信QQ邮件温度计

点击上方“蘑菇云创造”可以关注我们哦


项目设计

可通过微信直接看到家里的室温,不用打开微信小程序或其它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服务,同时通过手机发送验证短信,生成授权码。




微信开启QQ邮箱提醒


步骤:

https://kf.qq.com/touch/faq/150612YrMBvY150612YN3mUz.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)





本文来源:DF创客社区

作者:云天






蘑菇云创造

微信号 : mgystem

扫码关注,了解更多






推荐阅读:



【声明】内容源于网络
0
0
蘑菇云创造
蘑菇云是DFRobot旗下专注于AI人工智能、创客、STEAM、劳动教育的科技创新教育品牌;以为中国培养下一代科技创新人才为使命,为学校提供k12全龄段科技创新教育解决方案。
内容 969
粉丝 0
蘑菇云创造 蘑菇云是DFRobot旗下专注于AI人工智能、创客、STEAM、劳动教育的科技创新教育品牌;以为中国培养下一代科技创新人才为使命,为学校提供k12全龄段科技创新教育解决方案。
总阅读1.1k
粉丝0
内容969