欢迎使用 QuizzerBot!这是一个给服务器增加趣味答题活动的插件。支持Paper/Bukkit/Spigot等服务端核心。当前稳定支持API版本1.21.6及以上(已通过1.21.6-1.21.8版本测试,低于1.21.6尚未测试,但由于低版本不支持对话框API因此可能会出问题)。
本文档会尽量覆盖所有功能进行介绍,并区分新旧版本。当前文档对应版本:1.2.0
QuizzerBot 核心就是“答题”。它提供了两种完全独立的答题模式:
经典聊天答题 (所有版本均可使用)
图形界面答题 (1.2.0+ 新增, 需 MC 1.21.6+)
插件安装后会自动生成:
config.yml配置文件quizzerBook.db H2格式数据库文件数据库存储:
警告:请勿手动删除数据库文件,否则将导致数据丢失
1.2.0+ 版本 (最新):
1.1.x 版本:
plugins目录正常启动时会显示如下日志信息(具体内容可能因版本不同略有差异):
[11:15:17 INFO]: [QuizzerBot] 数据库初始化完成
[11:15:17 INFO]: [QuizzerBot] 配置项:最低玩家限制: 1
[11:15:17 INFO]: [QuizzerBot] 配置项:答题时间: 20
[11:15:17 INFO]: [QuizzerBot] 答题系统已成功启动插件第一次运行时,会自动在 plugins/QuizzerBot/ 目录下生成 config.yml 配置文件和 quizzerBook.db 数据库文件。1.2.0版本为了读写 .db 数据库,插件会自动从网上下载 H2 数据库驱动,下载速度取决于服务端所在服务器网络情况。
插件会根据 config.yml 里的 trigger_interval_sec: [最小值, 最大值] 配置,在这个时间范围内随机挑一个秒数,倒计时触发答题。(如果把最小值和最大值设成一样的,就是固定时间触发)。
触发时,会检查当前在线人数是否满足 min_players 的最低要求。
条件满足后,题目和选项会发到公屏。
玩家有 answer_reveal_delay_sec 秒的时间来作答(比如配置 60 秒)。
玩家可以通过直接点击聊天框里的选项或使用 /quiz ans <答案> 来提交。
时间一到,插件停止接收答案并开始结算。
插件会看 player_QuickAnswer_limit (抢答名额) 和 player_reward_limit (奖励名额) 这两个配置。
“抢答成功”: 最先答对的前 player_QuickAnswer_limit 名玩家,会被标记为“抢答成功”。
“获得奖励”: 插件会从“抢答成功”的玩家里,按先后顺序发奖励,最多发 player_reward_limit 份。
特殊情况: 如果抢答名额内的玩家答错了,奖励会顺延给后面答对的玩家 (哪怕他不是抢答玩家),直到发满 player_reward_limit 份奖励为止。
独立题库: 它使用一个叫 extra_questions 的独立题库,管理指令是 /quiz extra ...。
独立统计: 它的排行榜、玩家数据也是独立计算的。
玩法: 玩家输入 /quiz dialog 打开菜单,就可以自己选择题库(如果你未来做了分类)或开始答题。
应用场景: 非常适合做服主定制的内容,比如英语四六级单词(就像你开发的初衷!)、服务器趣味知识问答等。
为了方便服主编辑大量题目,1.2.0 版增加了 CSV 导入导出功能。
数据表列表(区分大小写):QuizzerBook extraQuizBook PlayerStats PlayerExtraStats
导出: /quiz database export <表名>
例如: /quiz database export QuizzerBook (导出自动答题的题库)
例如: /quiz database export PlayerExtraStats (导出附加题库)
导出的 .csv 文件会放在 plugins/QuizzerBot/ 目录下,并与数据表名同名,如“QuizzerBook.csv”
导入: /quiz database import <表名>
导入前需要保证要导入的表格文件名和数据表名一模一样(区分大小写),并放在plugins/QuizzerBot/目录中。
危险操作警告:
导入时,插件会先清空数据库里原有的整张表,然后再把你 .csv 文件里的内容全部写进去!
这意味着任何在游戏里用指令添加的题目都会被覆盖!
操作前建议先备份 quizzerBook.db 文件!
触发机制:
题目展示:
[11:31:02 INFO]: [答题Bot] 答题时间到~
===========问题编号: 1================
工作台需要几个木板合成?
A: 2 B: 4 C: 5 D: 7
=======================================
[11:31:02 INFO]: 答案在10秒后揭晓,【点击选项】即可答题作答方式:
/quiz ans <选项>抢答机制:
抢答成功后全服公告:
[11:32:37 INFO]: [答题Bot] yanhy2000 抢答成功![1/3]结果公布:
[11:32:41 INFO]: [答题Bot] 答案揭晓: 【B】!
抢答正确: 1人, 普通回答正确: 0人, 共发放奖励: 1人quiz:
# 配置文件版本,不要动
conf_version: 1
# (旧版配置,1.2.0+ 已移除语言文件,默认为 zh_CN)
# language: zh
# 触发聊天答题的最低在线玩家数
min_players: 1
# 答题触发间隔时间(秒),[最小值, 最大值]
# 在这个范围内随机一个时间点触发
trigger_interval_sec: [60, 120]
# 聊天答题开始后,玩家有多长时间作答(秒)
answer_reveal_delay_sec: 60
# 答对后给的奖励指令,%player% 会被替换成玩家名
reward_commands:
- 'say %player% 在答题中获胜!'
- 'give %player% diamond 1'
# 每人每天最多从聊天答题中获取多少次奖励
daily_reward_limit: 5
# 每轮聊天答题,最多发多少份奖励
player_reward_limit: 3
# 每轮聊天答题,前多少个回答的玩家算作“抢答”
# (答错了也算抢答名额)
player_QuickAnswer_limit: 3| 字段 | 类型 | 说明 |
|---|---|---|
| id | INTEGER | 自增主键 |
| quiz | TEXT | 题目内容(必填) |
| optA-optD | TEXT | 选项内容(可空) |
| answer | TEXT | 正确答案(A/B/C/D) |
| isEnable | BOOLEAN | 是否启用(默认TRUE) |
| showCount | INTEGER | 题目出现次数统计 |
| 字段 | 类型 | 说明 |
|---|---|---|
| uuid | TEXT | 玩家唯一标识 |
| username | TEXT | 玩家名 |
| total_attempts | INTEGER | 总答题次数 |
| correct_answers | INTEGER | 答对次数 |
| quick_answers | INTEGER | 抢答成功次数 |
| daily_rewards | INTEGER | 当日获得奖励数 |
| last_played_date | TEXT | 最后参与日期(YYYY-MM-DD) |
| 字段 | 类型 | 说明 |
|---|---|---|
| id | INTEGER | 自增主键 |
| type | TEXT | 题目类型(必填) |
| quiz | TEXT | 题目内容(必填) |
| optA-optD | TEXT | 选项内容(可空) |
| answer | TEXT | 正确答案(A/B/C/D) |
| isEnable | BOOLEAN | 是否启用(默认TRUE) |
| showCount | INTEGER | 题目出现次数统计 |
| 字段 | 类型 | 说明 |
|---|---|---|
| uuid | TEXT | 玩家唯一标识 |
| username | TEXT | 玩家名 |
| total_attempts | INTEGER | 总答题次数 |
| correct_answers | INTEGER | 答对次数 |
| last_played_date | TEXT | 最后参与日期(YYYY-MM-DD) |
权限:标有 (管理员) 的指令需要 OP 权限。
6.1 玩家命令
| 命令 | 说明 |
|---|---|
| /quiz ans <答案> | 提交“聊天答题”的答案 (A/B/C/D) |
| /quiz me | 查看你自己的答题统计 (聊天答题) |
| /quiz query <玩家> | 查看其他玩家的统计 (聊天答题) |
| /quiz top [类别] | 查看聊天答题的排行榜 (类别: total, correct, quick, rewards) |
| /quiz dialog | (1.2.0+) 打开“图形界面答题”菜单 |
6.2 管理员命令 (通用)
| 命令 | 说明 |
|---|---|
| /quiz reload | (管理员) 重载 config.yml 配置文件 |
| /quiz reset <玩家> | (管理员) 重置指定玩家的所有答题数据 (包括聊天和图形界面) |
| /quiz help | (管理员) 显示帮助菜单 |
6.3 管理员命令 (经典聊天答题)
| 命令 | 说明 |
|---|---|
| /quiz startnow | (管理员) 立即开始一轮聊天答题 |
| /quiz stop | (管理员) 停止自动答题的调度器 |
| /quiz enable <true/false> | (管理员) 启用或禁用自动答题调度器 |
| /quiz add <问题> | (管理员) 添加一道聊天答题 (答案是A/B/C/D) |
| /quiz delete | (管理员) 删除指定 ID 的聊天题目 |
| /quiz modify | (管理员) 修改聊天题目 (字段如: quiz, optA, answer...) |
| /quiz toggle | (管理员) 启用或禁用一道聊天题目 |
| /quiz list [页码] | (管理员) 列出所有聊天答题的题目 |
| /quiz detail | (管理员) 查看聊天题目的详细信息 |
6.4 管理员命令 (图形界面答题)
| 命令 | 说明 |
|---|---|
| /quiz extra add ... | (管理员) 添加题目到“图形界面”题库 (参数同上) |
| /quiz extra delete | (管理员) 删除“图形界面”题目 |
| /quiz extra modify | (管理员) 修改“图形界面”题目 |
| /quiz extra toggle | (管理员) 启用/禁用“图形界面”题目 |
| /quiz extra list | (管理员) 列出所有“图形界面”题目 |
| /quiz extra detail | (管理员) 查看“图形界面”题目详情 |
6.5 管理员命令 (数据库)
| 命令 | 说明 |
|---|---|
| /quiz database export <表名> | (管理员) 导出数据表到 CSV (表名: questions 或 extra_questions) |
| /quiz database import <表名> | (管理员) (危险操作) 从 CSV 导入数据,覆盖原表 |
1.1.x 旧版本不包含 extra, database新指令。
min_players设置添加题目示例:
/quiz add 低版本中Minecraft中钻石在第几层最多? 1-5 5-12 12-20 20+ b数据备份: 插件的数据库文件 quizzerBook.db 存着你所有的题目和玩家数据,建议定期备份
问题反馈: 遇到 Bug 或有啥好建议,欢迎联系 yanhy2000@foxmail.com
本Wiki文档随插件版本更新,最新版请以实际发布为准]]>

通过网盘分享的文件:海信A2Pro
链接: https://pan.baidu.com/s/1mqOTiOcziVDVPRBFGtoIiA?pwd=afuu 提取码: afuu
--来自百度网盘超级会员v5的分享
工具资源列表:
其他工具(见文章末尾):

简单介绍:
我自己的尝试是先刷入国际版系统,然后解锁BootLoader,最后刷入修补后的boot以实现root,因此该教程按我自己尝试路线进行。
刷机包提供的是国际版固件全量刷机包,如想刷其他国行固件,解锁等教程理论上都适用。
国际版系统我认为的几个好处:广告少,预置乱七八糟软件少,安装器很精简没有杀毒等,低耗电等。
注意:如果手机A2P是二手购买且恢复过出厂设置的,务必在恢复出厂设置后插入一次正常的SIM卡以激活USB(不消耗流量,可以不开数据流量),海信A2Pro手机有USB防护,必须插入一次SIM激活才能连接电脑传数据,否则只支持充电,无法用数据传输、安装驱动、USB调试等功能。
*1973461# ,会跳出一个系统信息(界面),点击调试设置,勾选自动加载USB设备。

cmd并回车
在cmd窗口内输入指令确保已经识别到设备 以重启手机到刷机模式(BootLoader Mode)
adb devices
如果显示未信任并且手机有弹窗选择是否信任计算机,需勾选信任并确认,然后再次执行指令和上图差不多
在cmd窗口内输入指令以重启手机到9008刷机模式(EDL Mode)
adb reboot edl
prog_emmc_firehose_8953_ddr_000460e1.mbnrawprogram_000460e1.xml,第二次弹窗选择patch0.xml
在开机状态下,打开开发者选项,勾选USB调试,勾选OEM解锁
如果想自己根据刷机包的boot来修补以root可以看下面这段,如果用文章内修补后的boot可跳过这段直接到刷入部分
cmd并回车在cmd窗口内输入指令以重启手机到BL模式(BootLoader Mode)(备注:经踩坑测试,发现重启到fastboot会正常开机,只有BootLoader下可以刷机,也就是不存在fastboot)
adb reboot bootloader
# 刷机后仍需要插入SIM卡来激活USB,并且需要重新在弹窗勾选信任计算机
# 等待两秒后,输入指令查看手机是否进入了BootLoader模式
fastboot devices
# 如果列表中有设备则为正常
在新的cmd窗口输入指令以解锁手机
fastboot Hisense unlockOKEY字样即为解锁成功,可关闭该cmd窗口。回到之前的CMD窗口,输入指令来刷入修补后的boot镜像
fastboot flash boot <敲空格后将boot镜像文件直接拖入>
如显示OKEY且没有错误信息,则刷入成功,输入指令重启
fastboot reboot开机后,打开Magisk软件,即可看到安装成功的版本信息

可正常授权root权限


海信的手机(不确定是不是都这样)在恢复出厂设置后需要 插入一次正常的SIM卡以激活USB (不消耗流量,可以不开数据流量),海信A2Pro手机有USB防护,必须插入一次SIM激活才能连接电脑传数据,否则只支持充电,无法用数据传输、安装驱动、USB调试等功能。
在内置的应用商店-应用恢复可以安装找回
如果为了精简系统禁用了应用商店或者单纯不想使用,可以在拨号盘输入 *#*#20019994#*#* 打开预置应用找回设置
刷机后发现墨水屏的天气一栏和主屏幕的时间与天气小组件,无法获取天气,说是要安装,但是安装总会失败,是因为国际版固件没有天气APP,只有Google提供的新闻与天气。在本文提供的资料文件里面已经从国行版固件提取出天气APP了,Chinaweather.apk,直接安装后即可使用,小组件也可以正常获取天气。
国行更新包目前只有卡刷OTA包,我找到一个相对全的Full包 A2T_L1467.6.07.01.00_full.zip,里面有Boot.img与更新的system.new.dat(或许也可以通过这个包9008刷入后,通过修补boot来实现国行固件root)。因此需要两个工具,[解包Bin2Img工具]sdat2img-master.zip该工具可以将更新文件合并到system.img,使用方法:
python sdat2img.py system.transfer.list system.new.dat system.img转换为system.img后,使用工具[提取system.img工具]ext2explore-2.2.71,加载该文件,即可看到内部全部文件。右键文件点击save,可将文件提取到外面。
*#*#4636#*#* ——服务菜单
*1973460# - FTMode
*1973461#或*#*#3647#*#* - 系统信息
*1973462# -操作员测试
*#0000# ——系统信息
*#06# -IMEI本文参考资料:
本章节待慢慢补充...
linux下的GPIO一般可以在/sys/kernel/debug/gpio下查询到信息,但是由于棒子的PCB没有开源,无法得知目前那些GPIO可以使用。但是通过表面可知,至少有3颗LED、2路SIM卡控制端口可用,且板载Uart串口调试点,因此,如果能对其中几个IO进行操作,通过IIC协议,即可可以控制多路外设,成为真正的硬件开发板...
从最简单的开始,控制一颗LED的亮灭。刷了Debian系统后,板子上只有红色、蓝色灯为启用状态,而绿色灯为None状态。因此,我们可以先拿没用的绿色LED下手。
查询目前棒子上已知的GPIO引用:ls /sys/class/leds/
查询后可得:
蓝色LED默认分配为WIFI状态
绿色LED默认分配为网络状态
红色LED默认为系统运行指示灯
SIM:EN为SIM卡启用状态,该焊盘位于ESIM底座GND处,预测SIM1同理
SIM:SEL为SIM选择状态,物理位置目前未测量
进入green的目录内,可看到以下几个文件:
主要文件为brightness、max_brightness、trigger,这三个文件即为LED引脚的属性
brightness:可读可写; 所以这个属性文件是用于设置 LED的亮度等级或者获取当前 LED 的亮度等级。
max_brightness: 该属性文件只能被读取,不能写,用于获取 LED 设备的最大亮度等级。
trigger: 触发模式,该属性文件可读可写,通过 cat 命令查看该属性文件触发模式
其中,trigger 内有以下的模式:
这里中括号选中为none,即为禁用。常见模式有:
timer:使用系统定时器控制,可用于作为伪PWM控制,定时闪烁等功能
heartbeat:心跳模式,可用于作为监控系统运行状态,定时有规律的闪烁
default-on:默认开启模式,此模式会使LED常亮,可用于寻找板载物理位置使用
mmc:读写存储器(emmc)的时候会闪烁
phy0tx(rx):接收(发送)wifi数据时会闪烁
使用echo的方式写入该文件即可控制LED的状态,如这里使它运行为心跳包闪烁模式:
echo heartbeat > /sys/class/leds/green\:internet/trigger同理,如果写入 none 则为禁用led灯,指令如下:
echo none > /sys/class/leds/green\:internet/trigger也可以设置led为wifi状态指示灯:
echo phy0radio > /sys/class/leds/green\:internet/trigger仅需执行指令,即可控制led状态,重启后恢复原始模式,可写入rc.local让其每次开机都设置为该模式。
可以将其设置为 timer 定时器模式,通过手动调整延时开与延时关的方式模拟PWM占空比:
echo timer > /sys/class/leds/green\:internet/trigger
echo 90 > /sys/class/leds/green\:internet/delay_off
echo 10 > /sys/class/leds/green\:internet/delay_on同理,可以使用绿色LED的IO用来控制风扇,实现温控风扇。以下代码为即兴发挥,可自行测试,将风扇连接至绿色LED引脚上,或者更改 GPIO_PIN 值为其他IO引脚;可以自行更改 pwm_v 的值,以1000为满值,分4个档位。代码仅供测试,如果有问题可评论区留言。
#python 3
import time
import os
pwm_v = [300,500,700,900] #档位速度设置,满值为1000
GPIO_PIN = "green\:internet" #IO引脚设置
print("开始初始化GPIO...")
os.system(f"echo timer > /sys/class/leds/{GPIO_PIN}/trigger")
while True:
time.sleep(1)
try:
temp_file=open("/sys/class/thermal/thermal_zone0/temp",'r')
temp = int(int(temp_file.read())/1000)
temp_file.close()
print(f"当前温度为:{temp}")
except OSError as e:
print(f"打开文件出错:{str(e)}")
if temp <25:
print(f"温度在(0,25)区间内,关闭风扇,PWM占空比0%")
os.system(f"echo 0 > /sys/class/leds/green\:internet/delay_on")
os.system(f"echo 1000 > /sys/class/leds/green\:internet/delay_off")
if temp >= 25 and temp <35:
print(f"温度在[25,35)区间内,开启第一档,高电平时间{pwm_v[0]},低电平时间{1000-pwm_v[0]},PWM占空比{pwm_v[0]/1000*100}%")
os.system(f"echo {pwm_v[0]} > /sys/class/leds/green\:internet/delay_on")
os.system(f"echo {1000-pwm_v[0]} > /sys/class/leds/green\:internet/delay_off")
if temp >= 35 and temp <45:
print(f"温度在[35,45)区间内,开启第二档,高电平时间{pwm_v[1]},低电平时间{1000-pwm_v[1]},PWM占空比{pwm_v[1]/1000*100}%")
os.system(f"echo {pwm_v[1]} > /sys/class/leds/green\:internet/delay_on")
os.system(f"echo {1000-pwm_v[1]} > /sys/class/leds/green\:internet/delay_off")
if temp >= 45 and temp <55:
print(f"温度在[45,55)区间内,开启第三档,高电平时间{pwm_v[2]},低电平时间{1000-pwm_v[2]},PWM占空比{pwm_v[2]/1000*100}%")
os.system(f"echo {pwm_v[2]} > /sys/class/leds/green\:internet/delay_on")
os.system(f"echo {1000-pwm_v[2]} > /sys/class/leds/green\:internet/delay_off")
if temp >= 55 and temp <65:
print(f"温度在[55,65)区间内,开启第四档,高电平时间{pwm_v[3]},低电平时间{1000-pwm_v[3]},PWM占空比{pwm_v[3]/1000*100}%")
os.system(f"echo {pwm_v[3]} > /sys/class/leds/green\:internet/delay_on")
os.system(f"echo {1000-pwm_v[3]} > /sys/class/leds/green\:internet/delay_off")
if temp >= 65:
print(f"温度大于65摄氏度,开启最大功率,PWM占空比100%")
os.system(f"echo 1000 > /sys/class/leds/green\:internet/delay_on")
os.system(f"echo 0 > /sys/class/leds/green\:internet/delay_off")
除了简单的控制LED的行为以及模拟PWM,这几个引出的IO或许还可以更改输出输入模式,待本文后续更新继续探索...
https://github.com/Yushi-Xing/openstick_fan/blob/main/main.cpp
https://gitee.com/anhui1995/ufi_auto-fan/blob/master/autofan.c
https://blog.csdn.net/qq_26226907/article/details/128027533
https://www.kancloud.cn/handsomehacker/openstick/2637560
还是准备玩esp32加小屏幕了,记录一下开发心得,虽然都做到一半多了,但是为了防止忘记或者是因为习惯性记录,还是准备将新学的给记下来,之前WIFI配网都做好了,那就从蓝牙开始吧...
原文参考链接:https://www.bilibili.com/read/cv15007387
硬件:ESP32
编程语言:Micropython
编译器:Thonny
目标:让esp32模块发出蓝牙信号,手机连接并通过软件发送串口数据,模块接收数据并实现点灯效果
基础测试代码:
from machine import Pin
from time import sleep_ms
import ubluetooth #导入BLE功能模块
ble = ubluetooth.BLE() #创建BLE设备
ble.active(True) #打开BLE
#设置BLE广播数据并开始广播
ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x03\x09\x41\x42')运行后,可以在手机上搜索到一个蓝牙设备名为“AB"
如要修改蓝牙名称,可这样修改:
name = bytes("aabbcc", 'UTF-8')
ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x02\x0A\x08' + bytearray((len(name)+1,0x09))+name)
一个中文占用3字节储存,而广播数据最多只有31字节,除去硬件配置外,命名也要限制一定字数
广播数据格式可参考:https://www.bilibili.com/read/cv15007387
注:由于esp32模块功率很小,发射的蓝牙信号较小,手机经常连接不上,可通过在广播数据格式内修改发射功率调整,对应的数据为x02x0Ax08 ,完整代码为:
name = bytes("aabbcc", 'UTF-8')
print("蓝牙开始广播")
ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x02\x0A\x08' + bytearray((len(name)+1,0x09))+name)蓝牙可连接后,需要让其处理各种事件,如蓝牙断开、连接以及收发等,可参考以下代码
详情:https://www.bilibili.com/read/cv15039837
from machine import Pin
from time import sleep_ms
import ubluetooth #导入BLE功能模块
ble = ubluetooth.BLE() #创建BLE设备
ble.active(True) #打开BLE(此时设备将处于就绪态)
#设置BLE广播数据并开始广播(开始广播后设备将处于广播态)
ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x03\x09\x41\x42')
#定义一个函数,用作蓝牙事件中断
def ble_irq(event, data): # 蓝牙中断函数
if event == 1: #蓝牙已连接(此时蓝牙将处于连接态)
print("BLE 连接成功")
elif event == 2: #蓝牙断开连接(此时蓝牙将从链接态进入就绪态)
print("BLE 断开连接")
ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x03\x09\x41\x42')#再次启动广播
elif event == 3: # 收到新write消息
print("BLE 收到新消息")
ble.irq(ble_irq) #注册蓝牙中断函数有了中断函数后,可以更方便监听到蓝牙状态。接下来就是准备连接手机并交互了
蓝牙服务与特性创建,详情:https://www.bilibili.com/read/cv15049793
通过注册蓝牙服务,可以使用安卓APP nRF Connect或者微信小程序 谷雨蓝牙调试 进行数据传输,其中服务id为9011特性一9012为可读可写,9013为可读与通知,从esp32到手机上的消息就是通过9013 Notify这个权限获取信息的。
完整代码:
from machine import Pin
from time import sleep_ms,sleep
import ubluetooth #导入BLE功能模块
sleep(1)
ble = ubluetooth.BLE() #创建BLE设备
ble.active(True) #打开BLE(此时设备将处于就绪态)
#创建要使用的UUID
SERVER_1_UUID = ubluetooth.UUID(0x9011)
CHAR_A_UUID = ubluetooth.UUID(0x9012)
CHAR_B_UUID = ubluetooth.UUID(0x9013)
#创建特性并设置特性的读写权限
CHAR_A = (CHAR_A_UUID, ubluetooth.FLAG_READ | ubluetooth.FLAG_WRITE | ubluetooth.FLAG_NOTIFY, )
CHAR_B = (CHAR_B_UUID, ubluetooth.FLAG_READ | ubluetooth.FLAG_NOTIFY, )
SERVER_1 = (SERVER_1_UUID, (CHAR_A , CHAR_B, ) , ) #把特性A和特性B放入服务1
SERVICES = (SERVER_1, ) #把服务1放入服务集和中
((char_a, char_b), ) = ble.gatts_register_services(SERVICES) #注册服务到gatts
#设置BLE广播数据并开始广播(开始广播后设备将处于广播态)
name = bytes("aabbcc", 'UTF-8')
print("蓝牙开始广播")
ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x02\x0A\x08' + bytearray((len(name)+1,0x09))+name)
#定义一个函数,用作蓝牙事件中断
def ble_irq(event, data): # 蓝牙中断函数
if event == 1: #蓝牙已连接(此时蓝牙将处于连接态)
print("BLE 连接成功")
elif event == 2: #蓝牙断开连接(此时蓝牙将从链接态进入就绪态)
print("BLE 断开连接")
ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x02\x0A\x08' + bytearray((len(name)+1,0x09))+name)#再次启动广播
elif event == 3: # 收到新write消息
onn_handle, char_handle = data #判断是来自那个特性的消息
buffer = ble.gatts_read(char_handle) #读取接收到的消息
print(char_handle, buffer) #打印消息内容
ble.gatts_notify(0, char_handle, 'Hello') #回复Hello
ble.irq(ble_irq) #注册蓝牙中断函数这段代码运行后,通过蓝牙调试软件连接模块后,监听9012特性,可对其发送数据,同时在thonny终端内也可以看到发送的数据,并且每发送一条数据,都会收到来自模块的Notify通道的”Hello"回复。
上述为读写数据创建特定的uuid,下面是较为常用的两种实际应用:
注册电池服务
#创建电池服务和特性的UUID
BATTERY_SERVER_UUID = ubluetooth.UUID(0x180F)
BATTERY_CHAR_UUID = ubluetooth.UUID(0x2A19)
#创建特性并设置特性的读写权限
BATTERY_CHAR = (BATTERY_CHAR_UUID, ubluetooth.FLAG_READ , )
BATTERY_SERVER = (BATTERY_SERVER_UUID, (BATTERY_CHAR, ) , ) #把电量特性放入电池服务
SERVICES = (BATTERY_SERVER, ) #把电池服务服务放入服务集和中
((battery_char,), ) = ble.gatts_register_services(SERVICES) #注册服务到gatts
ble.gatts_write(battery_char, b'\x50') #设置电池电量为80%注册温湿度服务
#创建环境传感器服务和特性的UUID
ENV_SERVER_UUID = ubluetooth.UUID(0x181A) #环境传感器服务
TEM_CHAR_UUID = ubluetooth.UUID(0x2A6E) #温度特性
HUM_CHAR_UUID = ubluetooth.UUID(0x2A6F) #湿度特性
#创建特性并设置特性的读写权限
TEM_CHAR = (TEM_CHAR_UUID, ubluetooth.FLAG_READ , )
HUM_CHAR = (HUM_CHAR_UUID, ubluetooth.FLAG_READ , )
ENV_SERVER = (ENV_SERVER_UUID, (TEM_CHAR, HUM_CHAR, ) , ) #把温湿度特性放入环境服务
SERVICES = (ENV_SERVER, ) #把环境服务放入服务集和中
((tem_char, hum_char, ), ) = ble.gatts_register_services(SERVICES) #注册服务到gatts
ble.gatts_write(tem_char, b'\x06\x08') #设置温度为20.54度(0x0806 = 2054)
ble.gatts_write(hum_char, b'\x09\x07') #设置湿度为18.01%(0x0709 = 1801)
对于一些常用的功能,蓝牙组织联盟已经为其定义好了UUID,我们在开发产品的时候直接使用即可。
16BitUUID定义文档下载地址:https://btprodspecificationrefs.blob.core.windows.net/assigned-values/16-bit%20UUID%20Numbers%20Document.pdf
最后把上面代码结合一起,就可以愉快用蓝牙点灯了!
使用方法:执行代码后,使用谷雨蓝牙连接,并监听9012服务中的read,发送任意数据,收到回复“hello”,发送“led_on”,led打开,收到回复“led on!”;发送“led_off”,led关闭,收到回复“led off!”
from machine import Pin
from time import sleep_ms,sleep
import ubluetooth #导入BLE功能模块
sleep(1)
ble = ubluetooth.BLE() #创建BLE设备
ble.active(True) #打开BLE(此时设备将处于就绪态)
led = Pin(2, Pin.OUT) #led引脚
#创建可读可写可通知的UUID
SERVER_1_UUID = ubluetooth.UUID(0x9011)
CHAR_A_UUID = ubluetooth.UUID(0x9012)
CHAR_B_UUID = ubluetooth.UUID(0x9013)
#创建特性并设置特性的读写权限
CHAR_A = (CHAR_A_UUID, ubluetooth.FLAG_READ | ubluetooth.FLAG_WRITE | ubluetooth.FLAG_NOTIFY, )
CHAR_B = (CHAR_B_UUID, ubluetooth.FLAG_READ | ubluetooth.FLAG_NOTIFY, )
SERVER_1 = (SERVER_1_UUID, (CHAR_A , CHAR_B, ) , ) #把特性A和特性B放入服务1
SERVICES = (SERVER_1, ) #把服务1放入服务集和中
((char_a, char_b), ) = ble.gatts_register_services(SERVICES) #注册服务到gatts
#设置BLE广播数据并开始广播(开始广播后设备将处于广播态)
name = bytes("aabbcc", 'UTF-8')
print("蓝牙开始广播")
ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x02\x0A\x10' + bytearray((len(name)+1,0x09))+name)
#定义一个函数,用作蓝牙事件中断
def ble_irq(event, data): # 蓝牙中断函数
if event == 1: #蓝牙已连接(此时蓝牙将处于连接态)
print("BLE 连接成功")
elif event == 2: #蓝牙断开连接(此时蓝牙将从链接态进入就绪态)
print("BLE 断开连接")
ble.gap_advertise(100, adv_data = b'\x02\x01\x06\x02\x0A\x08' + bytearray((len(name)+1,0x09))+name)#再次启动广播
elif event == 3: # 收到新write消息
onn_handle, char_handle = data #判断是来自那个特性的消息
buffer = ble.gatts_read(char_handle) #读取接收到的消息
print(char_handle, buffer,str(buffer, 'UTF-8')) #打印消息内容
if str(buffer, 'UTF-8')=="led_on":
led.on()
ble.gatts_notify(0, char_handle, 'led on!')
elif str(buffer, 'UTF-8')=="led_off":
led.off()
ble.gatts_notify(0, char_handle, 'led off!')
else:
ble.gatts_notify(0, char_handle, 'Hello')#回复Hello
ble.irq(ble_irq) #注册蓝牙中断函数
]]>经常为了在linux跑编译去安装虚拟机或者wsl,但其都有共同特征,即虚拟环境...为了更稳定的生产力以及学习linux,我找到了Fedora...
为搭建个正常的linux环境,我之前曾尝试了debian系的ubuntu、deepin、raspbian(PC版)、kali等,但因为都是同一系列的,总感觉操作有些乏味,于是找上了红帽系的系统,而Fedora正是红帽系广受欢迎的社区发行版系统,因此准备将其安装为第二系统。
这个系统使用体验不错,之前在搞服务器的时候用过centos,曾了解过yum软件包管理器等,但红帽系的系统操作还需学习,正好是个机会,写在博客上记录自己从安装双系统到优化fedora的日常使用。
安装完成后的截图:
因为日常开发还是windows系统,因此我选择从win来安装双系统。
因为考虑到可能日用,基本功能要有,所以这边选择工作站workstation版本下载。

在下载镜像的同时,打开分区软件(如diskgunius),为Fedora系统腾出一些空间(推荐60-80GB),将腾出的空间融为一块,且不创建新分区(后续Fedroa安装时会自动分配)(此文在fedroa系统下所写,因此无法提供截图)
下面操作步骤为回忆内容,至于为啥这么熟练,因为第一次分区分小了,重装了N次...
下载完毕后我选择使用u盘来安装(手头刚好有闲置u盘,其他的方法暂时不考虑),使用ultraiso将镜像写入到u盘,随后插入u盘,重启电脑,并按住F12不放(华为荣耀笔记本是F12选择启动设备,其他电脑自行查询),选择USB启动即可。
进入grub选择页后,直接选择默认的第一条进入即可,会进入到体验版系统,并会弹出系统安装引导软件。
选择中文、时区后,第三个选择硬盘需慎重。一般电脑内仅一块硬盘,选择默认硬盘后下方勾选自定义,再点左上角完成,会进入自定义分区页面
进入自定义分区页面后,确保下面显示空余空间为几十个GB而不是只有MB大小,如果是MB,可能分区的时候自动创建分区了,在下面列表找到目标分区后点下面的“-”号即可删除分区,小心不要把其他有重要数据的分区或者win系统分区删除了;如果是正常的几十GB,直接选择上面自动分区即可,无需多余操作,最后返回到主页面就可以开始安装系统了。
安装完成后,点击重启后拔出u盘,再次开机会自动引导到linux的grub启动,正常情况下grub启动项前两个分别是正常启动入口和恢复安全紧急模式入口,第三个引导项则是win的启动入口。(在fedora下,引导项无需且严重不推荐手动修改,系统会通过脚本自动找到可启动的linux内核,如果有安装多个版本,可以在系统内卸载旧内核版本,而不应该直接修改grub)
系统默认的grub可以说是非常简陋的了,因此在后面优化操作体验的时候会提到修改启动页面主题部门...
按照我个人的linux使用习惯,一般情况下没有国内优化的系统开箱第一件事就是换源了,不知道是不是错觉,没有换源总感觉装依赖都特别慢...
红帽系系统感觉换源还挺复杂的(之前给centos换源也是头疼了半天),这边就总结一下快捷指令吧,如果有特殊需要请做好备份
sudo sed -e 's|^metalink=|#metalink=|g' \
-e 's|^#baseurl=http://download.example/pub/fedora/linux|baseurl=https://mirrors.ustc.edu.cn/fedora|g' \
-i.bak \
/etc/yum.repos.d/fedora.repo \
/etc/yum.repos.d/fedora-modular.repo \
/etc/yum.repos.d/fedora-updates.repo \
/etc/yum.repos.d/fedora-updates-modular.repo中科大源帮助文档:https://mirrors.ustc.edu.cn/help/fedora.html
换源后输入sudo dnf makecache即可产生软件包缓存,随后即可yum update(yum、dnf都是软件包管理器)
换源后速度明显提升不少(截图来自fedora系统内置截图软件)(圆角好评
在这波更新后,浏览器、文件管理区、应用商店等众多软件都需要重新打开以生效新版本(至少我这个系统版本是这样,而且印象里内核还有个更新

应用商店打开速度也快了起来,软件包也能加载出来

一般在大型更新后,我是习惯输入sudo yum clean all来清理更新产生的缓存(原因是因为之前翻目录发现缓存cache目录占用特别大,查了一下发现很多软件包缓存),效果如图:

在较大更新或者应用商店明示你要更新内核时,更新完经常会留下旧内核,这时候就需要手动清理了(也可以不理会,就是开机引导时会有脚本把全部内核启动项给仍到grub,会显得不好看)
查看当前内核版本 uname -r
我这里提示版本为“5.14.10-300.fc35.x86_64”
查看系统内安装的内核相关包 rpm -qa | grep kernel
明显可以看出同一个包(如kernel-core)有两个不同的版本,再根据上面查到的当前内核版本,可以确定要卸载的包:
kernel-headers-5.14.9-300.fc35.x86_64
kernel-core-5.14.10-300.fc35.x86_64(旧版本需卸载)
kernel-modules-5.14.10-300.fc35.x86_64(旧版本需卸载)
kernel-5.14.10-300.fc35.x86_64(旧版本需卸载)
libreport-plugin-kerneloops-2.15.2-6.fc35.x86_64
abrt-addon-kerneloops-2.14.6-9.fc35.x86_64
kernel-modules-extra-5.14.10-300.fc35.x86_64(旧版本需卸载)
kernel-core-5.14.17-301.fc35.x86_64
kernel-modules-5.14.17-301.fc35.x86_64
kernel-5.14.17-301.fc35.x86_64
kernel-modules-extra-5.14.17-301.fc35.x86_64接下来,输入 sudo yum remove kernel-5.14.10-300.fc35.x86_64等手动移除这四个旧版本即可(-core可能无法移除,可重启后尝试)
最后输入reboot重启即可
至此,fedora已经安装完毕,且软件包等更新完成,可正常使用。想要了解更多玩法,欢迎继续关注本博客!
]]>Frp(Fast Reverse Proxy)是一个用于内网穿透反向代理应用,支持TCP、UDP等多种协议,可以将内网服务通过具有公网IP节点的服务器连接到公网,实际应用于本地服务器、树莓派建站等项目
前几期我们对树莓派进行了简单配置,但是仍没有将其投入到实际应用中。树莓派4b版性能强大,且运行功率较小,已经可以将其当成一个小型服务器使用了。因此本期内容就是为树莓派搭建个私人的Frp内网穿透服务器,以便于在树莓派上完成建站等项目。本次我们采用了64位系统的raspbian,在社区测试中,64位系统虽然功能尚未完善,但是其性能已经超出了官方原版32位系统很多,正合适用来配置小型服务器。
搭建Frp服务器时,一般使用各个大厂的学生机即可,推荐购买轻量应用服务器,1核2GB内存5M带宽的性能足够网站应用使用了,一般各个大厂的学生机每个月都是9块左右。虽然每个月限制1000GB流量,但是一般小型服务器除了音视频推流之外一般也用不完的。
阿里云学生机:https://developer.aliyun.com/plan/grow-up
腾讯云学生机:https://cloud.tencent.com/act/campus?from=12631
华为云学生机:https://developer.huaweicloud.com/campus?productType=KC1_1&timeType=1&domainItemData=
百度云学生机:https://cloud.baidu.com/campaign/campus-2018/index.html?unifrom=eventpage注:阿里云的学生机取消入口,只能通过各种活动或者类似于开发者成长计划获取“学生机”;
华为云学生机为鲲鹏云,使用arm架构CPU,开发环境不同,请斟酌选择;
百度云学生机带宽较低,看个人选择;
其他厂商可能也有类似活动,本章暂未列出
购买服务器后安装系统等操作可以直接参考服务商文档,本章不再列出
Frp的官方github开源页,里面可以下载到最新版本:https://github.com/fatedier/frp
1、通过ssh连接到服务器
2、先点击上面的链接前往github页面,找到右侧的Release,点击最新的版本,会看到很多个Frp版本
3、确认自己的服务器架构后(一般都是64位x86架构),在合适的版本上右击复制下载链接,一般情况下选择frp_xx.xx.xx_linux_amd64.tar.gz即可
4、在ssh输入 wget 复制的链接并回车即可开始下载,如:wget https://github.com/fatedier/frp/releases/download/v0.36.2/frp_0.36.2_linux_amd64.tar.gz
5、下载完后解压tar -zxvf frp_0.36.2_linux_amd64.tar.gz(后面为下载的文件名,如不同请自行替换)
6、简化文件夹名称mv frp_0.36.2_linux_amd64 frp重命名为frp文件夹,并进入文件夹cd frp
7、编辑Frp服务端的配置文件nano frps.ini(frps为服务端,frpc为客户端),如无特殊需要保持默认配置即可,修改完点击键盘上Ctrl+o保存,再点Ctrl+x退出
8、现在服务端的搭建临近尾声,输入sudo ./frps -c ./frps.ini即可运行,按下Ctrl+c停止运行
9、在服务器上使用守护进程systemctl:
在/lib/systemd/system文件夹下创建frps.service
Sudo vim frps.service
输入如下内容并保存退出
[Unit]
Description=frp service
After=network.target
[Service]
TimeoutStartSec=30
ExecStart=#frp完整路径#/frps -c #frp完整路径#/frps.ini
ExecStop=/bin/kill $MAINPID
[Install]
WantedBy=multi-user.target示例:
10、启动Frp服务:systemctl start frps,输入systemctl即可查看进程frps正在运行;
设置frps开机启动:systemctl enable frps
在win可视化界面,操作会变得非常简便
1、在服务器内打开浏览器前往https://github.com/fatedier/frp下载最新版本,选择amd64版本下载
2、解压后双击打开frps.ini配置文件,修改端口并保存
3、在文件夹地址栏输入cmd并回车,输入frps -c frps.ini即可运行frp服务器
4、要想设置frps服务器开机启动,只需要在地址栏输入C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp并进入,新建frps.bat并右键进入修改
5、修改bat文件,将以下内容复制进去:路径\frps.exe -c 路径\frps.ini即可实现开机启动,如:
在配置完frps后,仍需要去服务端网页后台的安全组处开放相应端口,如默认端口为7000,安全组需要添加tcp协议的7000端口;同时还需要再添加一个tcp协议的端口,作为映射出来的端口
按照前面服务端的方法下载frp到树莓派上并解压,这次将会用到压缩包内的frpc...
由于树莓派是arm架构,且本文使用的是树莓派的64位架构系统,因此在github我们下载frp_x.x.x_linux_arm64.tar.gz,下载、解压方法同服务端

1、先进入frp文件夹内cd frp
2、配置frpc.ini的相关信息nano frpc.ini
[common]
server_addr = 服务器的公网地址,比如1.1.1.1
server_port = 服务器frp的端口
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22 #22端口在linux里是ssh连接用的,设置为22端口可以通过frp进行远程ssh连接树莓派
remote_port = 6000 #要映射的端口,比如在ssh软件内输入连接 1.1.1.1:6000 即可连接到ssh的22端口3、保存并退出,输入./frpc -c ./frpc.ini即可连接到frp服务器
服务端:
客户端:
如果连接超时,请检查:
服务器网页端控制台有没有放行端口、是否服务器有防火墙或者宝塔等面板二次阻拦、配置文件是否一致、服务器时间是否正确
下载同上,然后解压后修改frpc.ini配置文件并保存
文件夹地址栏输入cmd回车,打开cmd后输入frpc.exe -c frpc.ini即可
Frp到此已经搭建完成了,之后我们就可以挂上frp做一些小项目了...
1、安装宝塔面板建站(64位系统):wget -O install.sh http://download.bt.cn/install/install-ubuntu_6.0.sh && sudo bash install.sh
2、NAS个人网盘:https://shumeipai.nxez.com/2018/11/01/a-raspberry-pi-nas-that-really-look-like-a-nas.html
3、MC游戏服务器(性能较低,联机用,仅java版):https://shumeipai.nxez.com/2013/11/21/how-to-run-low-cost-minecraft-on-a-raspberry-pi-for-block-building-on-the-cheap.html
4、安装远程桌面云办公:https://shumeipai.nxez.com/2013/10/06/windows-remote-desktop-connection-raspberry-pi.html
5、... ...