v2ray

trojan://bpb-trojan@www.vpslook.com:443?security=tls&sni=这里填域名&alpn=h3&fp=randomized&allowlnsecure=1&type=ws&host=这里填域名&path=%2Ftr%3Fed%3D2560#BPB
pip install requests beautifulsoup4
pip install selenium
import requests
from bs4 import BeautifulSoup
from packaging import version # 用于比较版本号

# FOFA 查询页面 URL
FOFA_URL = "https://fofa.info/result?qbase64=aWNvbl9oYXNoPSItMTM1NDAyNzMxOSIgJiYgYXNuPSIxMzMzNSIgJiYgcG9ydD0iNDQzIg%3D%3D"

# 文件名定义
OUTPUT_FILE_1 = "1.txt"
OUTPUT_FILE_2 = "2.txt"
OUTPUT_FILE_OK = "OK.txt"

def get_fofa_results():
"""抓取 FOFA 页面并提取结果地址"""
print("正在抓取 FOFA 页面...")
response = requests.get(FOFA_URL)
if response.status_code != 200:
print(f"无法访问 FOFA 页面,状态码:{response.status_code}")
return []

# 使用 BeautifulSoup 解析 HTML 内容
soup = BeautifulSoup(response.text, 'html.parser')
results = []

# 查找所有结果链接
for link in soup.find_all('a', href=True):
url = link['href']
if url.startswith("https://"): # 提取 https 开头的链接
results.append(url)

print(f"提取到 {len(results)} 个地址")
return results

def append_login_to_urls(input_file, output_file):
"""将地址加上 /login 并保存到新文件"""
print(f"正在处理 {input_file},将地址加上 /login 并保存到 {output_file}...")
with open(input_file, "r", encoding="utf-8") as infile, open(output_file, "w", encoding="utf-8") as outfile:
for line in infile:
url = line.strip() + "/login"
outfile.write(url + "\n")
print(f"已完成地址追加,结果保存到 {output_file}")

def check_bpb_version(input_file, output_file):
"""访问地址并检查 BPB Panel 的版本号"""
print(f"正在验证 {input_file} 中的地址...")
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
}
min_version = version.parse("2.5.3") # 最低版本号
with open(input_file, "r", encoding="utf-8") as infile, open(output_file, "w", encoding="utf-8") as outfile:
for line in infile:
url = line.strip()
try:
response = requests.get(url, headers=headers, timeout=10)
if response.status_code == 200 and "BPB Panel" in response.text:
# 提取版本号
raw_version = extract_version(response.text)
if raw_version:
parsed_version = version.parse(raw_version)
if parsed_version > min_version:
print(f"[匹配] {url} (版本号: {parsed_version})")
outfile.write(url + "\n")
except Exception as e:
print(f"[错误] 无法访问 {url},错误:{e}")
print(f"验证完成,符合条件的地址保存到 {output_file}")

def extract_version(html):
"""从 HTML 内容中提取 BPB Panel 的版本号"""
if "BPB Panel" in html:
start_index = html.find("BPB Panel")
# 提取版本号(假设版本号以 2 开头)
version_start = html.find("2", start_index)
version_end = version_start
while version_end < len(html) and (html[version_end].isdigit() or html[version_end] == "."):
version_end += 1
return html[version_start:version_end]
return None

def main():
# 第一步:抓取 FOFA 页面结果并保存到 1.txt
urls = get_fofa_results()
with open(OUTPUT_FILE_1, "w", encoding="utf-8") as f:
for url in urls:
f.write(url + "\n")
print(f"FOFA 页面结果已保存到 {OUTPUT_FILE_1}")

# 第二步:将 1.txt 地址加上 /login 并保存到 2.txt
append_login_to_urls(OUTPUT_FILE_1, OUTPUT_FILE_2)

# 第三步:验证 2.txt 中的地址,符合条件的保存到 OK.txt
check_bpb_version(OUTPUT_FILE_2, OUTPUT_FILE_OK)

if __name__ == "__main__":
main()
https://m.driftmycar.us.kg/login
https://cqbbbsd03.wangbuliao.us.kg/login
https://fdrc.us.kg/login
https://bpb.hlyf.us.kg/login
https://xiaolifeidao2024.us.kg/login
https://a.kexue001.us.kg/login
https://shaelyn.hedley.us.kg/login
https://ytymianban.yitianyang.us.kg/login
https://fj348014800.us.kg/login
https://singbox.xn--54qq5qftl6kf.us.kg/login
ss://YWVzLTI1Ni1jZmI6YW1hem9uc2tyMDU=@34.219.118.99:443#%F0%9F%87%BA%F0%9F%87%B8_US_%E7%BE%8E%E5%9B%BD
vless://bd1c2aac-e80d-46c5-bd18-f304b8dd8a27@151.101.66.219:80?security=none&type=ws&host=XpnTeam.ir&path=@XpnTeam/@XpnTeam/@XpnTeam/@XpnTeam/@XpnTeam/@XpnTeam/@XpnTeam/@XpnTeam/@XpnTeam/@XpnTeam/@XpnTeam/@XpnTeam/@XpnTeam/@XpnTeam/@XpnTeam/@XpnTeam%3Fed%3D2048#%F0%9F%87%BA%F0%9F%87%B8_US_%E7%BE%8E%E5%9B%BD
vless://f56e4463-f71a-4ab6-8074-534d2b1439c2@151.101.130.219:80?security=none&type=ws&host=snapp.com&path=%2FJoin--HAJIMAMADVPN--Join--HAJIMAMADVPN--Join--HAJIMAMADVPN--Join--HAJIMAMADVPN--Join--HAJIMAMADVPN--Join--HAJIMAMADVPN--Join--HAJIMAMADVPN--Join--HAJIMAMADVPN--Join--HAJIMAMADVPN--Join--HAJIMAMADVPN--Join--HAJIMAMADVPN--Join--HAJIMAMADVPN--Join--HAJIMAMADVPN%3Fed%3D2048#%F0%9F%87%BA%F0%9F%87%B8_US_%E7%BE%8E%E5%9B%BD
vmess://eyJhZGQiOiIxODUuMTkzLjMxLjEwOCIsImFpZCI6MCwiaG9zdCI6ImlwMTguNjkyOTE5OC54eXoiLCJpZCI6IjVmM2YwOWFkLTg5Y2ItNGU5NC1hN2FkLWFhODIzOTkxMzU1NSIsIm5ldCI6IndzIiwicGF0aCI6Ii9naXRodWIuY29tL0FsdmluOTk5OSIsInBvcnQiOjIwODIsInBzIjoi8J+Hs/Cfh7FfTkxf6I235YWwLT7wn4eo8J+Hpl9DQV/liqDmi7/lpKciLCJ0bHMiOiIiLCJ0eXBlIjoiYXV0byIsInNlY3VyaXR5IjoiYXV0byIsInNraXAtY2VydC12ZXJpZnkiOnRydWUsInNuaSI6IiJ9
ss://YWVzLTI1Ni1jZmI6YW1hem9uc2tyMDU=@47.128.246.130:443#%F0%9F%87%BA%F0%9F%87%B8_US_%E7%BE%8E%E5%9B%BD
vmess://eyJhZGQiOiI0NS44LjIxMS4yNDIiLCJhaWQiOjAsImhvc3QiOiJpcDE4LjY5MjkxOTgueHl6IiwiaWQiOiI1ZjNmMDlhZC04OWNiLTRlOTQtYTdhZC1hYTgyMzk5MTM1NTUiLCJuZXQiOiJ3cyIsInBhdGgiOiIvZ2l0aHViLmNvbS9BbHZpbjk5OTkiLCJwb3J0IjoyMDgyLCJwcyI6IvCfh6zwn4enX0dCX+iLseWbvS0+8J+HqPCfh6ZfQ0Ff5Yqg5ou/5aSnIiwidGxzIjoiIiwidHlwZSI6ImF1dG8iLCJzZWN1cml0eSI6ImF1dG8iLCJza2lwLWNlcnQtdmVyaWZ5Ijp0cnVlLCJzbmkiOiIifQ==
vmess://eyJhZGQiOiIxOTAuOTMuMjQ3LjIwMyIsImFpZCI6MCwiaG9zdCI6ImlwMTguNjkyOTE5OC54eXoiLCJpZCI6IjVmM2YwOWFkLTg5Y2ItNGU5NC1hN2FkLWFhODIzOTkxMzU1NSIsIm5ldCI6IndzIiwicGF0aCI6Ii9naXRodWIuY29tL0FsdmluOTk5OSIsInBvcnQiOjIwODIsInBzIjoi8J+HqPCfh7dfQ1Jf5ZOl5pav6L6+6buO5YqgLT7wn4eo8J+Hpl9DQV/liqDmi7/lpKciLCJ0bHMiOiIiLCJ0eXBlIjoiYXV0byIsInNlY3VyaXR5IjoiYXV0byIsInNraXAtY2VydC12ZXJpZnkiOnRydWUsInNuaSI6IiJ9
vless://520061ab-e8e3-4325-9272-8e3583094964@104.18.23.19:8080?security=none&type=ws&host=Operatormci.xn--nevergiveupyeoqkfsggy.bookmarkingonline.info.&path=%2F#%F0%9F%87%BA%F0%9F%87%B8_US_%E7%BE%8E%E5%9B%BD
vmess://eyJhZGQiOiIxOTAuOTMuMjQ2LjE5NiIsImFpZCI6MCwiaG9zdCI6ImlwMTguNjkyOTE5OC54eXoiLCJpZCI6IjVmM2YwOWFkLTg5Y2ItNGU5NC1hN2FkLWFhODIzOTkxMzU1NSIsIm5ldCI6IndzIiwicGF0aCI6Ii9naXRodWIuY29tL0FsdmluOTk5OSIsInBvcnQiOjIwODIsInBzIjoi8J+HqPCfh7dfQ1Jf5ZOl5pav6L6+6buO5YqgLT7wn4eo8J+Hpl9DQV/liqDmi7/lpKciLCJ0bHMiOiIiLCJ0eXBlIjoiYXV0byIsInNlY3VyaXR5IjoiYXV0byIsInNraXAtY2VydC12ZXJpZnkiOnRydWUsInNuaSI6IiJ9
vmess://eyJhZGQiOiIxOTAuOTMuMjQ0LjIyOCIsImFpZCI6MCwiaG9zdCI6ImlwMTguNjkyOTE5OC54eXoiLCJpZCI6IjVmM2YwOWFkLTg5Y2ItNGU5NC1hN2FkLWFhODIzOTkxMzU1NSIsIm5ldCI6IndzIiwicGF0aCI6Ii9naXRodWIuY29tL0FsdmluOTk5OSIsInBvcnQiOjIwODIsInBzIjoi8J+HuvCfh7hfVVNf576O5Zu9LT7wn4eo8J+Hpl9DQV/liqDmi7/lpKciLCJ0bHMiOiIiLCJ0eXBlIjoiYXV0byIsInNlY3VyaXR5IjoiYXV0byIsInNraXAtY2VydC12ZXJpZnkiOnRydWUsInNuaSI6IiJ9
vmess://eyJ2IjoiMiIsInBzIjoi8J+Hq/Cfh7dfRlJf5rOV5Zu9LT7wn4eo8J+Hpl9DQV/liqDmi7/lpKciLCJhZGQiOiIxNDYuMTkuMjEuNjEiLCJwb3J0IjoiMjA4MiIsInR5cGUiOiJub25lIiwiaWQiOiI1ZjNmMDlhZC04OWNiLTRlOTQtYTdhZC1hYTgyMzk5MTM1NTUiLCJhaWQiOiIwIiwibmV0Ijoid3MiLCJwYXRoIjoiL2dpdGh1Yi5jb20vQWx2aW45OTk5IiwiaG9zdCI6ImlwMTguNjkyOTE5OC54eXoiLCJ0bHMiOiIifQ==
ss://YWVzLTI1Ni1nY206UmV4bkJnVTdFVjVBRHhH@38.110.1.3:7002#%F0%9F%87%BA%F0%9F%87%B8_US_%E7%BE%8E%E5%9B%BD
trojan://5e2ce79c-170e-484a-8802-40584a1a3a12@naiu-us.05vr9nyqg5.download:13020?security=tls&sni=cloudflare.node-ssl.cdn-alibaba.com&type=tcp&headerType=none#%E6%9C%AA%E7%9F%A5
vless://16c95530-8276-5477-9e61-799542e502c7@140.248.139.207:80?type=ws&host=ADOLF-ELENA.IR#%F0%9F%87%BA%F0%9F%87%B8_US_%E7%BE%8E%E5%9B%BD
ss://YWVzLTI1Ni1jZmI6YW1hem9uc2tyMDU=@52.43.67.42:443#%F0%9F%87%BA%F0%9F%87%B8_US_%E7%BE%8E%E5%9B%BD
vmess://eyJhZGQiOiIxNTkuMTEyLjIzNS4zNSIsImFpZCI6MCwiaG9zdCI6ImlwMTguNjkyOTE5OC54eXoiLCJpZCI6IjVmM2YwOWFkLTg5Y2ItNGU5NC1hN2FkLWFhODIzOTkxMzU1NSIsIm5ldCI6IndzIiwicGF0aCI6Ii9naXRodWIuY29tL0FsdmluOTk5OSIsInBvcnQiOjIwODIsInBzIjoi8J+HuvCfh7hfVVNf576O5Zu9LT7wn4eo8J+Hpl9DQV/liqDmi7/lpKciLCJ0bHMiOiIiLCJ0eXBlIjoiYXV0byIsInNlY3VyaXR5IjoiYXV0byIsInNraXAtY2VydC12ZXJpZnkiOnRydWUsInNuaSI6IiJ9
vless://6ac07096-da0a-454a-a8b0-c7dc54a9f163@151.101.2.228:80?security=none&type=ws&host=ujhf5r5gub.com&path=ws%2F%3Fed%3D2048#%F0%9F%87%BA%F0%9F%87%B8_US_%E7%BE%8E%E5%9B%BD
ss://YWVzLTI1Ni1jZmI6YW1hem9uc2tyMDU=@54.186.178.129:443#%F0%9F%87%BA%F0%9F%87%B8_US_%E7%BE%8E%E5%9B%BD
ss://YWVzLTI1Ni1jZmI6YW1hem9uc2tyMDU=@18.136.105.175:443#%F0%9F%87%B8%F0%9F%87%AC_SG_%E6%96%B0%E5%8A%A0%E5%9D%A1-%3E%F0%9F%87%BA%F0%9F%87%B8_US_%E7%BE%8E%E5%9B%BD
ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTowOTgzM2E2Zi00ZDQ2LTQyNmUtODdmZS03NzkzYTU0ODlmODQ=@h-k01.loveroise.com:54000#%F0%9F%87%A8%F0%9F%87%B3_CN_%E4%B8%AD%E5%9B%BD-%3E%F0%9F%87%AB%F0%9F%87%B7_FR_%E6%B3%95%E5%9B%BD
ss://YWVzLTI1Ni1jZmI6VVRKQTU3eXBrMlhLUXBubUAyMTcuMzAuMTAuMTg6OTAzMw==#%F0%9F%87%B7%F0%9F%87%BA_RU_%E4%BF%84%E7%BD%97%E6%96%AF
vmess://eyJhZGQiOiIxODUuMTQ4LjEwNy4xMSIsImFpZCI6MCwiaG9zdCI6ImlwMTguNjkyOTE5OC54eXoiLCJpZCI6IjVmM2YwOWFkLTg5Y2ItNGU5NC1hN2FkLWFhODIzOTkxMzU1NSIsIm5ldCI6IndzIiwicGF0aCI6Ii9naXRodWIuY29tL0FsdmluOTk5OSIsInBvcnQiOjIwODIsInBzIjoi8J+HsfCfh7lfTFRf56uL6Zm25a6bLT7wn4eo8J+Hpl9DQV/liqDmi7/lpKciLCJ0bHMiOiIiLCJ0eXBlIjoiYXV0byIsInNlY3VyaXR5IjoiYXV0byIsInNraXAtY2VydC12ZXJpZnkiOnRydWUsInNuaSI6IiJ9
vless://03633612-cb32-46cc-8f93-7103d1511ade@151.101.2.216:80?security=none&type=ws&host=Mahxraytdep.ir&path=%2F%3Fed%3D80#%F0%9F%87%BA%F0%9F%87%B8_US_%E7%BE%8E%E5%9B%BD
vmess://eyJ2IjoiMiIsInBzIjoi8J+HuvCfh7hfVVNf576O5Zu9LT7wn4eo8J+Hpl9DQV/liqDmi7/lpKciLCJhZGQiOiIxOTAuOTMuMjQ1Ljc2IiwicG9ydCI6IjIwODIiLCJ0eXBlIjoibm9uZSIsImlkIjoiNWYzZjA5YWQtODljYi00ZTk0LWE3YWQtYWE4MjM5OTEzNTU1IiwiYWlkIjoiMCIsIm5ldCI6IndzIiwicGF0aCI6Ii9naXRodWIuY29tL0FsdmluOTk5OSIsImhvc3QiOiJpcDE4LjY5MjkxOTgueHl6IiwidGxzIjoiIn0=
vless://3983dfa7-c19e-4ef9-a635-122cd78a802e@45.81.35.6:33156?security=none&type=tcp#%F0%9F%87%AB%F0%9F%87%B7_FR_%E6%B3%95%E5%9B%BD
vless://520061ab-e8e3-4325-9272-8e3583094964@104.18.22.19:8080?security=none&type=ws&host=Operatormci.xn--nevergiveupyeoqkfsggy.bookmarkingonline.info.&path=%2F#%F0%9F%87%BA%F0%9F%87%B8_US_%E7%BE%8E%E5%9B%BD-%3E%F0%9F%87%A9%F0%9F%87%AA_DE_%E5%BE%B7%E5%9B%BD

备份并恢复wordpress

确保备份数据可恢复

当备份完成后,确保目标机器上的备份数据能够成功恢复,备份的数据库和文件都能够在目标系统上重新安装并运行 WordPress。

1. 恢复文件

在目标机器上,你可以使用 rsync 将备份的 WordPress 文件恢复到适当的目录(例如 /var/www/html/wordpress/):

bash复制代码rsync -avz /backup/wordpress/ /var/www/html/wordpress/

2. 恢复数据库

在目标机器上,你可以使用 mysqlmariadb 将备份的数据库恢复:

bash复制代码mysql -u wp_user -p'wp_password' wordpress_db < /backup/wordpress_db/wordpress_db.sql

确保在目标机器上,数据库的连接配置(wp-config.php 文件中的数据库设置)与源机器相同,确保 WordPress 可以成功连接到恢复的数据库。

修改MagicMirror2的 compliments 模块的中文字体风格

/* 修改 compliments 模块的中文字体风格 */
.compliments {
  font-size: 30px; /* 可以根据需要调整这个值 */
  color: #00ff00; /* 设置字体颜色为绿色 */
  font-family: "PingFang Light", "PingFang SC", sans-serif; /* 设置中文字体风格为 PingFang Light */
}

翻译

pip install googletrans==4.0.0-rc1
import json
from googletrans import Translator

def translate_file(input_file, output_file):
    # 初始化翻译器
    translator = Translator()

    with open(input_file, 'r', encoding='utf-8') as file:
        lines = file.readlines()

    translated_lines = []
    
    for line in lines:
        translated_lines.append(line)  # 保留原文
        if line.strip():  # 仅翻译非空行
            translation = translator.translate(line.strip(), src='en', dest='zh-cn')
            translated_line = line[:len(line) - len(line.lstrip())] + translation.text + ',\n'
            translated_lines.append(translated_line)

    with open(output_file, 'w', encoding='utf-8') as file:
        file.writelines(translated_lines)

# 指定输入和输出文件路径
input_file = 'input.json'
output_file = 'output.json'

# 运行翻译程序
translate_file(input_file, output_file)

同一行的程序

import json
from googletrans import Translator

def translate_text(text, src='en', dest='zh-cn'):
    translator = Translator()
    translated = translator.translate(text, src=src, dest=dest)
    return translated.text

def translate_json_object(obj, translator):
    if isinstance(obj, dict):
        return {k: translate_json_object(v, translator) for k, v in obj.items()}
    elif isinstance(obj, list):
        return [translate_json_object(i, translator) for i in obj]
    elif isinstance(obj, str):
        return obj + '\\' + translate_text(obj)
    else:
        return obj

def translate_json_file(input_file, output_file):
    with open(input_file, 'r', encoding='utf-8') as file:
        data = json.load(file)
    
    translator = Translator()
    translated_data = translate_json_object(data, translator)
    
    with open(output_file, 'w', encoding='utf-8') as file:
        json.dump(translated_data, file, ensure_ascii=False, indent=4)

input_file = 'input.json'
output_file = 'output.json'
translate_json_file(input_file, output_file)

sim key and mouse

nano /etc/rc.local

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi
sudo modprobe uinput
sudo /usr/bin/python3 /home/jack/Downloads/r_gpio_ok_over.py &
sudo /usr/bin/python3 /home/jack/start/joystick_ok.py &
exit 0

sudo su

pip3 install python-uinput

r_gpio_over.py

#!/usr/bin/env python
import RPi.GPIO as GPIO
import uinput
device = uinput.Device([
    uinput.KEY_LEFTSHIFT,
    uinput.KEY_TAB,
    uinput.KEY_SPACE
    ])

RoAPin = 17    # CLK Pin
RoBPin = 18    # DT Pin
BtnPin = 27    # Button Pin

globalCounter = 0
flag = 0
BtnFlag = 0
Last_RoB_Status = 0
Current_RoB_Status = 0
Current_Btn_Status = 0

def setup():
    GPIO.setmode(GPIO.BCM)       # Numbers GPIOs by physical location
    GPIO.setup(RoAPin, GPIO.IN)    # input mode
    GPIO.setup(RoBPin, GPIO.IN)
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

def rotaryDeal():
    global flag
    global Last_RoB_Status
    global Current_RoB_Status
    global globalCounter
    global BtnFlag
    global Current_Btn_Status
    Last_RoB_Status = GPIO.input(RoBPin)    
    while(not GPIO.input(RoAPin)):
        Current_RoB_Status = GPIO.input(RoBPin)
        flag = 1
    if flag == 1:
        flag = 0
        if (Last_RoB_Status == 1) and (Current_RoB_Status == 0):
            globalCounter = globalCounter + 1  #顺时针旋转,角位移增大
            device.emit_combo([uinput.KEY_LEFTSHIFT,uinput.KEY_TAB,])
        if (Last_RoB_Status == 0) and (Current_RoB_Status == 1):
            globalCounter = globalCounter - 1  #逆时针旋转,数值减小
            device.emit_combo([uinput.KEY_TAB,])
    while(not GPIO.input(BtnPin)):      #未按下按钮时,GPIO.input(BtnPin)值为1,按下时会变为0
        Current_Btn_Status = GPIO.input(BtnPin)  #按下按钮时的当前值
        BtnFlag = 1
    if BtnFlag == 1:
        BtnFlag = 0
        device.emit_combo([uinput.KEY_SPACE])

def btnISR(channel):
    global globalCounter
    globalCounter = 0

def loop():
    global globalCounter
    tmp = 0 # Rotary Temperary
    GPIO.add_event_detect(BtnPin, GPIO.FALLING, callback=btnISR)
    #当按下按钮时,调用回调函数btnISR
    while True:
        rotaryDeal()
        if tmp != globalCounter:
            print('globalCounter = %d' % globalCounter)
            tmp = globalCounter

def destroy():
    GPIO.cleanup()             # Release resource

if __name__ == '__main__':     # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()

joystick.py

import multiprocessing
import time
import RPi.GPIO as GPIO
import uinput

# 初始化输入GPIO引脚,将引脚拉低
GPIO.setmode(GPIO.BCM) # 使用BCM方式编号
up_pin = 5 # 可对照前文中管脚编号定义
down_pin = 6
left_pin = 13
right_pin = 19
left_button_pin = 20
right_button_pin = 12
GPIO.setup(up_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # 将管脚均设置为输入上拉模式
GPIO.setup(down_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(left_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(right_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(left_button_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(right_button_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# 创建虚拟输入设备(鼠标)
device = uinput.Device([uinput.BTN_LEFT, uinput.BTN_RIGHT, uinput.REL_X, uinput.REL_Y])

XY_STEP = 1 # 用于调节光标的移动步长

# 定义一个通用四向摇杆按键操作的进程处理函数
def direction_key_process(queue, pin, direction):
    while True:
        GPIO.wait_for_edge(pin, GPIO.BOTH) # 该进程Pending等待四向摇杆按键发生动作
        while GPIO.input(pin) == direction: # 如果是有效的低电平,那么它将持续向队列写入管脚编号
            queue.put(pin)
            time.sleep(0.005) # 此延迟可调节光标灵敏度

# 定义一个通用处理左右按键操作的进程
def leftright_key_process(queue, pin):
    while True:
        GPIO.wait_for_edge(pin, GPIO.BOTH) # 该进程Pending等待左/右按键发生动作
        queue.put(pin) # 一旦有状态变化,则将按键编号写入队列

# 定义一个更新光标位置的进程处理函数
def update_position_device():
    while True:
        pin = position_queue.get() # 该进程Pending等待方向按键队列数据
        if pin == up_pin:
            device.emit(uinput.REL_Y, -XY_STEP) # 根据按键方向移动光标XY轴位置
        elif pin == down_pin:
            device.emit(uinput.REL_Y, XY_STEP)
        elif pin == left_pin:
            device.emit(uinput.REL_X, -XY_STEP)
        elif pin == right_pin:
            device.emit(uinput.REL_X, XY_STEP)

# 定义一个更新左右按钮状态的进程处理函数
def update_button_device():
    while True:
        pin = button_queue.get() # 该进程Pending等待左右按键队列数据
        if pin == left_button_pin:
            if GPIO.input(pin) == GPIO.LOW:
                device.emit(uinput.BTN_LEFT, 1) # 按键按下
            else:
                device.emit(uinput.BTN_LEFT, 0) # 按键释放
        elif pin == right_button_pin:
            if GPIO.input(pin) == GPIO.LOW:
                device.emit(uinput.BTN_RIGHT, 1)
            else:
                device.emit(uinput.BTN_RIGHT, 0)

# 为方向按键、左右建分别创建一个队列来保存按键操作的引脚
position_queue = multiprocessing.Queue()
button_queue = multiprocessing.Queue()

# 创建多个进程来处理按键和按钮事件(每个按钮一个进程,互不影响)
processes = [
    multiprocessing.Process(target=direction_key_process, args=(position_queue, up_pin, GPIO.LOW)),
    multiprocessing.Process(target=direction_key_process, args=(position_queue, down_pin, GPIO.LOW)),
    multiprocessing.Process(target=direction_key_process, args=(position_queue, left_pin, GPIO.LOW)),
    multiprocessing.Process(target=direction_key_process, args=(position_queue, right_pin, GPIO.LOW)),
    multiprocessing.Process(target=leftright_key_process, args=(button_queue, left_button_pin)),
    multiprocessing.Process(target=leftright_key_process, args=(button_queue, right_button_pin))
]

# 启动所有进程
for p in processes:
    p.daemon = True # 设置为守护进程,即在主进程结束时自动结束
    p.start()

# 启动两个进程来更新设备状态
update_position_process = multiprocessing.Process(target=update_position_device)
update_position_process.daemon = True # 设置为守护进程,即在主进程结束时自动结束
update_position_process.start()

update_button_process = multiprocessing.Process(target=update_button_device)
update_button_process.daemon = True # 设置为守护进程,即在主进程结束时自动结束
update_button_process.start()

# 等待所有进程结束
for p in processes:
    p.join()

update_position_process.join()
update_button_process.join()

yixia wei yanzheng

r_gpio_tab_space_ok.py

import RPi.GPIO as GPIO
import time
from sys import version_info
import uinput
device = uinput.Device([
    uinput.KEY_LEFTSHIFT,
    uinput.KEY_TAB,
    uinput.KEY_SPACE,
    uinput.KEY_LEFTALT
    ])

if version_info.major == 3:
    raw_input = input

# Set up pins
# Rotary A Pin
RoAPin = 17
# Rotary B Pin
RoBPin = 18
# Rotary Switch Pin
RoSPin = 27

def print_message():
    print ("========================================")
    print ("|            Rotary Encoder            |")
    print ("|    ------------------------------    |")
    print ("|        Pin A connect to GPIO17       |")
    print ("|        Pin B connect to GPIO18       |")
    print ("|     Button Pin connect to GPIO27     |")
    print ("|                                      |")
    print ("|         Use a Rotary Encoder         |")
    print ("|     Rotary to add/minus counter      |")
    print ("|      Press to set counter to 0       |")
    print ("|                                      |")
    print ("|                            SunFounder|")
    print ("========================================\n")
    print ("Program is running...")
    print ("Please press Ctrl+C to end the program...")
    #raw_input ("Press Enter to begin\n")

def setup():
    global counter
    global Last_RoB_Status, Current_RoB_Status
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(RoAPin, GPIO.IN)
    GPIO.setup(RoBPin, GPIO.IN)
    GPIO.setup(RoSPin,GPIO.IN, pull_up_down=GPIO.PUD_UP)
    # Set up a falling edge detect to callback clear
    GPIO.add_event_detect(RoSPin, GPIO.FALLING, callback=clear)

    # Set up a counter as a global variable
    counter = 0
    Last_RoB_Status = 0
    Current_RoB_Status = 0

# Define a function to deal with rotary encoder
def rotaryDeal():
    global counter
    global Last_RoB_Status, Current_RoB_Status

    flag = 0
    Last_RoB_Status = GPIO.input(RoBPin)
    # When RoAPin level changes
    while(not GPIO.input(RoAPin)):
        Current_RoB_Status = GPIO.input(RoBPin)
        flag = 1
    if flag == 1:
        # Reset flag
        flag = 0
        if (Last_RoB_Status == 0) and (Current_RoB_Status == 1):
            counter = counter + 1
#            time.sleep(0.5)
            device.emit_combo([
            #    uinput.KEY_LEFTALT,
                uinput.KEY_LEFTSHIFT,
                uinput.KEY_TAB,
                ])
        if (Last_RoB_Status == 1) and (Current_RoB_Status == 0):
            device.emit_combo([
                uinput.KEY_SPACE,
#                uinput.KEY_TAB,
                ])
            counter = counter - 1
        print ("counter = %d" % counter)

# Define a callback function on switch, to clean "counter"
def clear(ev=None):
    global counter
    counter = 0

def main():
    print_message()
    while True:
        rotaryDeal()

def destroy():
    # Release resource
    GPIO.cleanup()

# If run this script directly, do:
if __name__ == '__main__':
    setup()
    try:
        main()
    # When 'Ctrl+C' is pressed, the child program
    # destroy() will be  executed.
    except KeyboardInterrupt:
        destroy()