https://gitee.com/mirrors_robert-hh/bme680-micropython
BME680 全包
后期
BMP280+AHT10
SGP-41 氮氧化合物 CO气体检测
https://gitee.com/mirrors_robert-hh/bme680-micropython
BME680 全包
后期
BMP280+AHT10
SGP-41 氮氧化合物 CO气体检测
广播 100ms 间隔高速率
import bluetooth, struct
#汉字一个3B,注意 最大8个汉字 100ms 广播高速率
def ble_name(dev_name):
if len(dev_name)>26:
return False
ble = bluetooth.BLE()
ble.active(False)
ble.active(True)
adv_data = struct.pack('BBB', 0x02, 0x01, 0x06)
name_bytes = dev_name.encode()
adv_data += struct.pack('B', 1 + len(name_bytes)) + b'\x09' + name_bytes
ble.gap_advertise(None)
ble.gap_advertise(100000, adv_data)
print("广播启动,名称:", dev_name," 长度:",len(dev_name))
return True
from micropython import const
import bluetooth
import time
# 常量定义
_IRQ_SCAN_RESULT = const(5)
AD_TYPE_NAME_COMPLETE = const(0x09)
AD_TYPE_NAME_SHORT = const(0x08)
ble = bluetooth.BLE()
device_set = set()
def _parse_name(adv_data):
i = 0
while i < len(adv_data):
ad_len = adv_data[i]
if ad_len == 0:
break
ad_type = adv_data[i+1]
payload = adv_data[i+2:i+1+ad_len]
if ad_type in (AD_TYPE_NAME_COMPLETE, AD_TYPE_NAME_SHORT):
try:
return payload.decode("utf-8").strip()
except:
return "Unreadable"
i += ad_len + 1
return "NoName"
def _scan_callback(event, data):
global device_set
if event == _IRQ_SCAN_RESULT:
_, _, _, _, adv_data = data
name = _parse_name(bytes(adv_data))
device_set.add(name)
def scan_ble_devices():
"""
阻塞扫描1秒,返回周围蓝牙设备名称列表(去重)
return: list[str]
"""
global device_set
device_set.clear()
# 初始化蓝牙与回调
ble.active(True)
ble.irq(_scan_callback)
# 扫描时长1000ms,高速抓包参数
ble.gap_scan(1000, 30000, 28000, 1)
# 阻塞等待最多1秒
t_start = time.ticks_ms()
while time.ticks_diff(time.ticks_ms(), t_start) < 1000:
pass
# 停止扫描、关闭蓝牙
ble.gap_scan(None)
ble.active(False)
# 转列表返回
return list(device_set)
# 调用示例
if __name__ == "__main__":
names = scan_ble_devices()
print("扫描到蓝牙设备:")
for n in names:
print("-", n)
#返回
#names = scan_ble_devices()
开启服务 start_background_full_scan()然后返回扫描的设备列表 scan_ble_devices()
from micropython import const
import bluetooth
import time
# BLE常量
_IRQ_SCAN_RESULT = const(5)
AD_TYPE_NAME_COMPLETE = const(0x09)
AD_TYPE_NAME_SHORT = const(0x08)
ble = bluetooth.BLE()
# 存储结构 {设备名称: 最后收到广播时间戳}
dev_cache = dict()
SCAN_RUNNING = False
# 设备超时时间:1500ms未收到广播判定离开
DEV_TIMEOUT = 1500
def _parse_name(adv_data):
"""解析广播包中的蓝牙设备名称"""
idx = 0
data_len = len(adv_data)
while idx < data_len:
ad_len = adv_data[idx]
if ad_len == 0:
break
ad_type = adv_data[idx + 1]
payload = adv_data[idx + 2 : idx + 1 + ad_len]
if ad_type in (AD_TYPE_NAME_COMPLETE, AD_TYPE_NAME_SHORT):
try:
return payload.decode("utf-8").strip()
except Exception:
return "Unreadable_Device"
idx += ad_len + 1
return "No_Name"
def ble_irq_callback(event, data):
global dev_cache
if event == _IRQ_SCAN_RESULT:
_, _, _, _, adv_data = data
dev_name = _parse_name(bytes(adv_data))
now = time.ticks_ms()
# 更新该设备最后活跃时间
dev_cache[dev_name] = now
def start_background_full_scan():
"""启动后台永久高速扫描,匹配100ms间隔信标"""
global SCAN_RUNNING
if SCAN_RUNNING:
return
ble.active(True)
ble.irq(ble_irq_callback)
# gap_scan(永久扫描0, 扫描周期100000us=100ms, 监听窗口90000us=90ms, 主动扫描1)
ble.gap_scan(0, 100000, 90000, 1)
SCAN_RUNNING = True
print("后台BLE扫描已启动 | 适配100ms间隔蓝牙信标")
def scan_ble_devices():
"""
对外调用接口:瞬间返回当前在场蓝牙设备名称列表
自动清理超时消失的设备,无阻塞
return: list[str]
"""
global dev_cache
if not SCAN_RUNNING:
return []
now = time.ticks_ms()
# 过滤超时设备
valid_devs = []
for name, last_tick in dev_cache.items():
if time.ticks_diff(now, last_tick) < DEV_TIMEOUT:
valid_devs.append(name)
return valid_devs
def stop_ble_scan():
"""停止扫描、关闭蓝牙,程序结束时调用"""
global SCAN_RUNNING
if not SCAN_RUNNING:
return
ble.gap_scan(None)
ble.active(False)
SCAN_RUNNING = False
dev_cache.clear()
print("BLE扫描已关闭")
------------------- 测试示例 -------------------
if __name__ == "__main__":
# 程序启动只执行一次,开启后台扫描
start_background_full_scan()
# 循环读取设备列表,随便高频调用无压力
while True:
dev_list = scan_ble_devices()
print("==== 在场蓝牙设备 ====")
if len(dev_list) == 0:
print("无设备")
else:
for name in dev_list:
print("-", name)
# time.sleep_ms(500)
<div class="row text-center">
<div class="pagination">{$info->render()|raw}</div>
<p class="text-muted">---共计<b class="text-danger">{$info->total()}</b>条---</p>
</div>
public function list(Pt12345Service $Pt12345Service){
$status=$this->request->get('status/d',0);
$info=['status'=>$status];
$list=$Pt12345Service->search($info);
#查询结果中将查询条件打包带入
$list->appends($this->request->param());
$department=$Pt12345Service->department();
$this->assign(['info'=>$list,"department"=>$department]);
return $this->fetch();
}
public function search($info){
$where=[];
if(isset($info['status'])){
if($info['status']<10){
$where[]=['status','=',$info['status']];
}
}
$list = Pt12345Model::where($where)
->order('id desc')
->paginate(20, false, ['query' => $info]);
#使用paginate分页,代替select,并且false,之后query内容未传入的$info变量
return $list;
}
Python3.8.10
selenium可以pip安装
chrome 109最后一个win7 版本,chromedriver 同样需要注意版本(存放位置后使用Service设置路径 )
编写时候注意:
find_elements()返回对象列表,find_element()返回对象!
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
service = Service(r"c:\chromedriver.exe")
driver = webdriver.Chrome(service=service)
driver.get("http://baidu.com/#/login")
#CLASS 选择器
driver.find_element(By.CLASS_NAME,"el-icon-arrow-up").click()
swap_c_s=driver.find_elements(By.CLASS_NAME, "el-select-dropdown__item")
time.sleep(3)
swap_c_s[7].click()
swap_c_v=driver.find_elements(By.CLASS_NAME,"el-input__inner")
#设置信息使用send_keys("")
swap_c_v[1].send_keys("admin")
swap_c_v[2].send_keys("admin")
driver.find_element(By.CLASS_NAME,"el-button--primary").click()
#Xpath选择器
driver.find_element(By.XPATH,'//span[contains(text(),"办理系统")]').click()
time.sleep(3)
打开页面必须 time.sleep 等待页面加载【JS动态页面必须注意AJAX回传也需要等待加载】
swap_tr_ones=driver.find_elements(By.XPATH,'(//table[contains(@class,"el-table__body")])[1]//tr')
for i in swap_tr_ones:
tid=i.find_element(By.XPATH,'.//td[4]').text
end=i.find_element(By.XPATH,'.//td[8]').text
#选择页面打开后 可以text 获取信息
打开新页面,需要使用driver.switch_to.window(driver.window_handles[1])
切换到之前的需要driver.switch_to.window(driver.window_handles[0]),上面二者后需要重新使用选择器抓取 ,关闭页面必须使用driver.close()
swap_click_ones=driver.find_elements(By.XPATH,'//table[contains(@class,"el-table__body")]//tr/td[4][not(contains(@class,"hidden"))]')
vx=[]
for i in swap_click_ones:
i.click()
time.sleep(3)
driver.switch_to.window(driver.window_handles[1])
driver.find_element(By.XPATH,'//span[contains(text(),"查看")]').click()
#切换到新页面 老的页面 driver.switch_to.window(driver.window_handles[0])
tid=driver.find_element(By.XPATH,'//label[contains(text(),"abc:")]/following-sibling::div/div').text
phone=driver.find_element(By.XPATH,'//label[contains(text(),"电话")]/following-sibling::div').text
info=driver.find_element(By.XPATH,'//label[contains(text(),"内容")]/following-sibling::div').text
one={
'tid':tid,
'phone':phone,
'info':info,
}
vx.append(one)
driver.close()
driver.switch_to.window(driver.window_handles[0])
图片保存图片
driver.save_screenshot("full_page.png")
元素保存图片
# 定位图片元素
img = driver.find_element(By.XPATH, "//img")
# 全屏截图临时文件
driver.save_screenshot("tmp.png")
full_img = Image.open("tmp.png")
# 获取元素位置尺寸
x = img.location['x']
y = img.location['y']
w = img.size['width']
h = img.size['height']
# 裁剪并保存
crop = full_img.crop((x, y, x + w, y + h))
crop.save("target_img.png")# 定位图片元素
img = driver.find_element(By.XPATH, "//img")
# 全屏截图临时文件
driver.save_screenshot("tmp.png")
full_img = Image.open("tmp.png")
# 获取元素位置尺寸
x = img.location['x']
y = img.location['y']
w = img.size['width']
h = img.size['height']
# 裁剪并保存
crop = full_img.crop((x, y, x + w, y + h))
crop.save("target_img.png")
Download 下载内容
https://www.python.org/downloads/release/python-3810
https://registry.npmmirror.com/binary.html?path=chromedriver/109.0.5414.74