import utptime
uftptime.settime() #同步網絡時間
這次我們在OneNET平臺上新建數據流,同時使用MQTT協議中publish報文格式上傳數據點。
MQTT協議實現方式
實現MQTT協議需要客戶端和服務器端通訊完成,在通訊過程中,MQTT協議中有三種身份:
發佈者(Publish):發佈數據點
代理(Broker)(服務器):接受C端連接,處理髮,訂,退,轉數據信息
訂閱者(Subscribe):訂閱數據點
其中,消息的發佈者pub和訂閱者sub都是客戶端,消息代理broker是服務器,消息發佈者可以同時是訂閱者。
MQTT傳輸的消息分爲:主題(Topic)和負載(payload)兩部分:
- (1)Topic,可以理解爲消息的類型,訂閱者訂閱(Subscribe)後,就會收到該主題的消息內容(payload);
- (2)payload,可以理解爲消息的內容,是指訂閱者具體要使用的內容。
Payload消息體
Payload消息體位MQTT數據包的第三部分,包含CONNECT、SUBSCRIBE、SUBACK、UNSUBSCRIBE四種類型的消息:
- (1)CONNECT,消息體內容主要是:客戶端的ClientID、訂閱的Topic、Message以及用戶名和密碼。
- (2)SUBSCRIBE,消息體內容是一系列的要訂閱的主題以及QoS。
- (3)SUBACK,消息體內容是服務器對於SUBSCRIBE所申請的主題及QoS進行確認和回覆。
- (4)UNSUBSCRIBE,消息體內容是要訂閱的主題。
from umqtt.simple import MQTTClient
from machine import Pin
import network
import time
import json
CLIENT_ID = "588234870" #設備ID
username = "3297741" #產品ID
password = "vaGMSmffsdfecCzMz4rs7y=rQ8gmo=" #APIKEY
SERVER = 'mqtt.heclouds.com' #183.230.40.39
TOPIC = 'wefdaidu'
state = 0
c=None
def sub_cb(topic, msg):
global state
print((topic, msg))
if msg == b"on":
#led.value(1)
state = 0
print("1")
elif msg == b"off":
#led.value(0)
state = 1
print("0")
elif msg == b"toggle":
#led.value(state)
state = 1 - state
#要上報的數據點
message = {'datastreams':[{'id':'temperature','datapoints':[{'value':27}]}]}
def pub_data(data): #組合成協議要求的報文格式
j_d = json.dumps(data)
j_l = len(j_d)
arr = bytearray(j_l + 3)
arr[0] = 1 #publish數據類型爲json
arr[1] = int(j_l / 256) # json數據長度 高位字節
arr[2] = j_l % 256 # json數據長度 低位字節
arr[3:] = j_d.encode('ascii') # json數據
return arr
def main():
server=SERVER
c = MQTTClient(CLIENT_ID, server,6002,username,password,keepalive=60) #創建客戶端連接
c.set_callback(sub_cb) #set callback
c.connect() #connect mqtt
c.subscribe(TOPIC) #訂閱
c.publish('$dp',pub_data(message)) #發佈
#print('publish message:',message)
time.sleep(5)
try:
while 1:
c.wait_msg()
except:
c.disconnect()
if __name__ == '__main__':
while True:
main()
注:
OneNet平臺設備保活
MQTT connect 報文中,需要設置keepalive(即保活時間),keepalive支持範圍爲:10~1800,單位爲秒
設備若需保持長連接,則設備在連續的設置的keepalive 時間內,必須要有上行數據報文(包括 publish、ping、subscribe 等)
平臺若在連續的 設置的keepalive的1.5倍 的時間內沒有收到設備上行數據,則會設備斷開連接
-------------------------------
繼電器使用
簡單原理圖 5v降壓模塊
因GPIO口輸出電流不足,繼電器操作可以引用電源或上拉一個10K電阻來觸發控制信號
-------------------------------------------
python操作mysql數據庫
一、Python連接MySQL數據庫
#導入模塊
import pymysql
#打開數據庫連接數據庫testdb
db = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='1234', db='testdb', charset='utf8')
#使用cursor方法創建一個遊標
cursor = db.cursor()
#查詢數據庫版本
cursor.execute("select version()")
data = cursor.fetchone()
print(" Database Version:%s" % data)
#創建數據庫test
cursor.execute("drop database if exists test") #如果數據庫已經存在,那麼刪除後重新創建
sql = "create database test"
cursor.execute(sql)
#創建數據庫表
cursor.execute("drop table if exists employee") #如果數據表已經存在,那麼刪除後重新創建
sql = """
CREATE TABLE EMPLOYEE (
FIRST_NAME CHAR(20) NOT NULL,
LAST_NAME CHAR(20),
AGE INT,
SEX CHAR(1),
INCOME FLOAT )
"""
cursor.execute(sql)
#查詢數據表數據
sql = "select * from employee"
cursor.execute(sql)
data = cursor.fetchone()
print(data)
#插入數據
sql = "insert into employee values ('李','梅',20,'W',5000)"
cursor.execute(sql)
db.commit()
#查看插入後的結果
sql = "select * from employee"
cursor.execute(sql)
data = cursor.fetchone()
print(data)
#指定條件查詢數據表數據
sql = " select * from employee where income > '%d' " % (1000)
cursor.execute(sql)
data = cursor.fetchone()
print(data)
#更新數據庫
sql = " update employee set age = age+1 where sex = '%c' " % ('W')
cursor.execute(sql)
db.commit()
#查看更新後的結果
sql = "select * from employee"
cursor.execute(sql)
data = cursor.fetchone()
print(data)
#刪除數據
sql = " delete from employee where age > '%d' " % (30)
cursor.execute(sql)
db.commit()
#查看更新後的結果
sql = "select * from employee"
cursor.execute(sql)
data = cursor.fetchone()
print(data)
#關閉數據庫
db.close()
二、增、刪、改、查
增、刪、改:conn.commit()
獲取數據:fetchone
,fetchall
,fetchmany
獲取插入數據自增ID:cursor.lastrowid
1、增、改
import pymysql
user = '小黑'
pwd = '06161086'
conn = pymysql.connect(host='localhost',user='root',password='',database='db1')
cursor = conn.cursor()
sql = "insert into userinfo(user,password) values(%s,%s)"#增
# sql = "update userinfo set password='06161088' where user='耿娃'"#改
r = cursor.execute(sql,user,pwd)#返回值r爲受影響的行數
# cursor.executemany(sql,[
# ('小張','06161085'),
# ('小王','06161084'),
# ('小段','06161083'),
# ('小余','06161082')])提交多條數據
conn.commit()
print(cursor.lastrowid)
cursor.close()
conn.close()
2、查
import pymysql
conn = pymysql.connect(host='localhost',user='root',password='',database='db1')
# cursor = conn.cursor()
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
sql = "select * from userinfo" #查
r = cursor.execute(sql) #返回值r爲受影響的行數
# cursor.scroll(1,mode='relative') #相對當前位置移動
# cursor.scroll(2,mode='absolute') #相對絕對位置移動
# ret = cursor.fetchone()
# ret = cursor.executemany(4) #一次取四個
ret = cursor.fetchall()
for rev in ret:
print(rev)
cursor.close()
conn.close()
3、執行存儲過程
cursor.callproc('p1') #執行存儲過程
三、其他說明
1、說明
·上例中"sql=..."語句,是經典的MySQL語句的形式,將數據庫語句寫在雙引號內,形成類似字符串的形式;
·使用cursor對象的execute()方法具體執行數據庫的操作;
·對於插入、更新、刪除等操作,需要使用db.commit()來提交到數據庫執行,對於查詢、創建數據庫和數據表的操作不需要此語句。
2、爲有效避免因爲錯誤導致的後果,使用以下方式來執行數據庫的操作:
try:
# 執行 SQL 語句
cursor.execute(sql)
# 提交修改
db.commit()
except:
# 發生錯誤時回滾
db.rollback()