git commit emoji

commit 格式

git commit 时,提交信息遵循以下格式:

1
2
3
4
5
:emoji1: :emoji2: 主题

提交信息主体

Ref <###>

初次提交示例:

1
git commit -m ":tada: Initialize Repo"

emoji 指南

emoji emoji 代码 commit 说明
🎨 (调色板) :art: 改进代码结构/代码格式
⚡ (闪电)🐎 (赛马) :zap:``:racehorse: 提升性能
🔥 (火焰) :fire: 移除代码或文件
🐛 (bug) :bug: 修复 bug
🚑 (急救车) :ambulance: 重要补丁
✨ (火花) :sparkles: 引入新功能
📝 (备忘录) :memo: 撰写文档
🚀 (火箭) :rocket: 部署功能
💄 (口红) :lipstick: 更新 UI 和样式文件
🎉 (庆祝) :tada: 初次提交
✅ (白色复选框) :white_check_mark: 增加测试
🔒 (锁) :lock: 修复安全问题
🍎 (苹果) :apple: 修复 macOS 下的问题
🐧 (企鹅) :penguin: 修复 Linux 下的问题
🏁 (旗帜) :checked_flag: 修复 Windows 下的问题
🔖 (书签) :bookmark: 发行/版本标签
🚨 (警车灯) :rotating_light: 移除 linter 警告
🚧 (施工) :construction: 工作进行中
💚 (绿心) :green_heart: 修复 CI 构建问题
⬇️ (下降箭头) :arrow_down: 降级依赖
⬆️ (上升箭头) :arrow_up: 升级依赖
👷 (工人) :construction_worker: 添加 CI 构建系统
📈 (上升趋势图) :chart_with_upwards_trend: 添加分析或跟踪代码
🔨 (锤子) :hammer: 重大重构
➖ (减号) :heavy_minus_sign: 减少一个依赖
🐳 (鲸鱼) :whale: Docker 相关工作
➕ (加号) :heavy_plug_sign: 增加一个依赖
🔧 (扳手) :wrench: 修改配置文件
🌐 (地球) :globe_with_meridians: 国际化与本地化
✏️ (铅笔) :pencil2: 修复 typo

参考

折腾斐讯K2刷LEDE

昨天又看到有人上车,于是没有经受住诱惑,撸了一台蓝色的斐讯K2,不知道能不能安全下车。颜值嘛还可以。做功嘛略显粗糙。打开看了一下配置。MT7620,64M的RAM和8M的ROM。。。这也能标399的价格,也是呵呵了。

首先刷一个优秀的Bootloader,这里我选择Breed,毕竟当年的U-Boot已经不行了。
这里有一个神奇的方法可以刷入Breed,不禁让我对作者的脑洞感到由衷的佩服。只有一句“这TM也行”可以表达我的内心想法了。

http://www.right.com.cn/forum/thread-204435-1-1.html

刷完Breed以后重启长按reset就可以进入刷机模式,就可以刷入系统固件了。
多年经验告诉我Openwrt是个好固件,然而去年openwrt内部出现了一些问题。导致有一部分核心人员独立出来成立了LEDE-Project。全称Linux Embedded Development Environment(名字起的好霸气啊),想想以前那么多的openwrt版本,那么混乱的Issue管理和补丁发布。这次还是试试LEDE吧。毕竟是新项目,又是openwrt的核心团队搞的,应该会不错的。

LEDE官网在此

在官网一搜,居然有K2的专门版本。这下好了,不用自己编译了。交叉编译搞死人。搜索PHICOMM K2 PSG1218就可以找到了。这里也贴一下下载地址
刷完之后重启。看到一个丑丑的Luci界面。

配置好密码和网络等基本配置。还剩90%的剩余空间。爽啊。果断准备安装全套[不可描述]、[不可描述]和[不可描述]的软件。
安装过程中就不写了。水表已拆。说一句现在安装和编译东西比几年前我搞hg255d的时候简单方便多了。又不用考虑剩余内存。简直是一帆风顺啊。
嗯再放一个获取中国国内IP列表的脚本吧。

wget -O- 'http://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest' | awk -F\| '/CN\|ipv4/ { printf("%s/%d\n", $4, 32-log($5)/log(2)) }' > /etc/不可描述.txt

最后装一个luci-i18n汉化包和theme包美化一下。结束战斗。

测试一下2.4G+5G(虽然我只开了5G)信号都还是不错的。速度也还算稳定。[不可描述]的速度也能跑满带宽。十分满意。最后贴个界面图,这个 luci-theme-material还是挺好看的。
图

MYSQL事务隔离级别

Mysql有四种事务隔离级别,分别是:
Read Uncommitted
Read Committed
Repeatable Read
Serializable

关于这四个隔离级别的介绍:

未提交读(READ UNCOMMITTED)。另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据(脏读)。

提交读(READ COMMITTED)。本事务读取到的是最新的数据(其他事务提交后的)。问题是,在同一个事务里,前后两次相同的SELECT会读到不同的结果(不重复读)。

可重复读(REPEATABLE READ)。在同一个事务里,SELECT的结果是事务开始时时间点的状态,因此,同样的SELECT操作读到的结果会是一致的。但是,会有幻读现象(稍后解释)。

串行化(SERIALIZABLE)。读操作会隐式获取共享锁,可以保证不同事务间的互斥。

这四个级别逐渐增强,每个级别解决一个问题

脏读,最容易理解。另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据。

不重复读。解决了脏读后,会遇到,同一个事务执行过程中,另外一个事务提交了新数据,因此本事务先后两次读到的数据结果会不一致。

幻读。解决了不重复读,保证了同一个事务里,查询的结果都是事务开始时的状态(一致性)。但是,如果另一个事务同时提交了新数据,本事务再更新时,就会“惊奇的”发现了这些新数据,貌似之前读到的数据是“鬼影”一样的幻觉。

可以通过select @@tx_isolation来查看当前隔离级别

通过set [ global | session ] transaction isolation level Read uncommitted | Read committed | Repeatable | Serializable来修改事务隔离级别

如果选择global,意思是此语句将应用于之后的所有session,而当前已经存在的session不受影响。

如果选择session,意思是此语句将应用于当前session内之后的所有事务。

如果什么都不写,意思是此语句将应用于当前session内的下一个还未开始的事务。

采用Arduino IDE对ESP8266进行编程

话说ESP8266真是个神奇的芯片,不仅可以使用NodeMCU和micropython等固件,还可以直接支持采用Arduino IDE环境进行编程和烧写。本身又有wifi和gpio,又便宜。简直是折腾神器。

采用Arduino编程的最大好处是,很多库可以直接引用。不用再写一些很底层的代码去驱动外设。这大大提高的开发效率,并且像上篇文章里写的,采用lua语言的NodeMCU还是有一些局限性的。比如不支持微秒级的延时。

要采用Arduino对ESP8266进行编程,首先要有一个1.6.4版本以上的Arduino IDE

其次在设置里需要把additional board manager URLs 设置为http://arduino.esp8266.com/stable/package_esp8266com_index.json

这样在工具里的开发板选择里就有了NodeMCU1.0选项。

下载完工具链就可以直接编写了。

下面是用Arduino写的gp2y1010au0f粉尘检测来测AQI的代码。测试通过

/*
   NodeMCU连接夏普GP2Y1010AU0F空气质量传感器检测PM2.5
*/
/* 定义引脚 */
#define PIN_DATA_OUT A0 //连接空气质量传感器模拟量输出的IO口, NodeMCU只有A0可以作为ADC
#define PIN_LED_VCC 5 //空气质量传感器中为内部Led供电的引脚
/* 定义时间 */
const int DELAY_BEFORE_SAMPLING = 280; //采样前等待时间
const int DELAY_AFTER_SAMPLING = 40; //采样后等待时间
const int DELAY_LED_OFF = 9680; //间隔时间
/**
   读取输出电压
*/
double getOutputV() {
  digitalWrite(PIN_LED_VCC, LOW);
  delayMicroseconds(DELAY_BEFORE_SAMPLING);
  double analogOutput = analogRead(PIN_DATA_OUT);
  delayMicroseconds(DELAY_AFTER_SAMPLING);
  digitalWrite(PIN_LED_VCC, HIGH);
  delayMicroseconds(DELAY_LED_OFF);
  //Arduino模拟量读取值的范围为0~1023,以下换算为0~5v
  double outputV = analogOutput / 1024 * 5;
  return outputV;
}
/**
   根据输出电压计算灰尘密度
*/
double getDustDensity(double outputV) {
  //输出电压和灰尘密度换算公式: ug/m3 = (V - 0.9) / 5 * 1000
  double ugm3 = (outputV - 0.9) / 5 * 1000;
  //去除检测不到的范围
  if (ugm3 < 0) {
    ugm3 = 0;
  }
  return ugm3;
}
/**
   根据灰尘密度计算AQI
   环境空气质量指数(AQI)技术规定(试行)](http://kjs.mep.gov.cn/hjbhbz/bzwb/dqhjbh/jcgfffbz/201203/t20120302_224166.htm
*/
double getAQI(double ugm3) {
  double aqiL = 0;
  double aqiH = 0;
  double bpL = 0;
  double bpH = 0;
  double aqi = 0;
  //根据pm2.5和aqi对应关系分别计算aqi
  if (ugm3 >= 0 && ugm3 <= 35) {
    aqiL = 0;
    aqiH = 50;
    bpL = 0;
    bpH = 35;
  } else if (ugm3 > 35 && ugm3 <= 75) {
    aqiL = 50;
    aqiH = 100;
    bpL = 35;
    bpH = 75;
  } else if (ugm3 > 75 && ugm3 <= 115) {
    aqiL = 100;
    aqiH = 150;
    bpL = 75;
    bpH = 115;
  } else if (ugm3 > 115 && ugm3 <= 150) {
    aqiL = 150;
    aqiH = 200;
    bpL = 115;
    bpH = 150;
  } else if (ugm3 > 150 && ugm3 <= 250) {
    aqiL = 200;
    aqiH = 300;
    bpL = 150;
    bpH = 250;
  } else if (ugm3 > 250 && ugm3 <= 350) {
    aqiL = 300;
    aqiH = 400;
    bpL = 250;
    bpH = 350;
  } else if (ugm3 > 350) {
    aqiL = 400;
    aqiH = 500;
    bpL = 350;
    bpH = 500;
  }
  //公式aqi = (aqiH - aqiL) / (bpH - bpL) * (desity - bpL) + aqiL;
  aqi = (aqiH - aqiL) / (bpH - bpL) * (ugm3 - bpL) + aqiL;
  return aqi;
}
/**
   根据aqi获取级别描述
*/
String getGradeInfo(double aqi) {
  String gradeInfo;
  if (aqi >= 0 && aqi <= 50) {
    gradeInfo = String("Perfect");
  } else if (aqi > 50 && aqi <= 100) {
    gradeInfo = String("Good");
  } else if (aqi > 100 && aqi <= 150) {
    gradeInfo = String("Mild polluted");
  } else if (aqi > 150 && aqi <= 200) {
    gradeInfo = String("Medium polluted");
  } else if (aqi > 200 && aqi <= 300) {
    gradeInfo = String("Heavily polluted");
  } else if (aqi > 300 && aqi <= 500) {
    gradeInfo = String("Severely polluted");
  } else {
    gradeInfo = String("Broken roof!!!");
  }
  return gradeInfo;
}
void setup() {
  Serial.begin(115200);
  pinMode(PIN_DATA_OUT, INPUT); //定义为输入(ADC读取模拟量)
  pinMode(PIN_LED_VCC, OUTPUT); //定义为输出
}
void loop() {
  double outputV = getOutputV(); //采样获取输出电压
  double ugm3 = getDustDensity(outputV); //计算灰尘浓度
  double aqi = getAQI(ugm3); //计算aqi
  String gradeInfo = getGradeInfo(aqi); //计算级别
  //打印到串口
  Serial.println(String("outputV=") + outputV + "\tug/m3=" + ugm3 + "\tAQI=" + aqi + "\tgradeInfo=" + gradeInfo);
  //间隔1秒执行下次检测
  delay(1000);
}

采用NodeMCU和GP2Y1010AU0F检测空气质量

夏普GP2Y1010AU0F传感器用于检测空气中的灰尘浓度。可以检测非常细小的灰尘,例如香烟烟雾(粒径0.1~2um)。
该传感器中心有一个孔洞,可使空气自由穿过。内部有一个LED向孔洞进行照射。当空气中的灰尘穿过孔洞时,光线反射到接收端,通过放大电路将反射光强放大并转化为输出电压。通过测量输出电压并进行响应的换算,即可得知空气中灰尘的浓度。

GP2Y1010AU0F引脚连接

(1)V-LED + 150ohm电阻 + 220uF电容->VCC
(2)LED-GND->GND
(3)LED->D1(GPIO 5)
(4)S-GND->GND
(5)VO->A0
(6)VCC->VCC

其中需要加150ohm电阻和220uF电容,连接方式如下图中红框所示:

connect

可以直接使用NodeMCU的adc即A0接口进行采样。先对GPIO 5拉低产生一个采样脉冲,读取A0的adc数据,即为输出电压。转换后可得粉尘浓度。代码如下

pin1 = 1
gpio.mode(pin1, gpio.OUTPUT) 
tmr.alarm(1, 2000, 1, function()
    gpio.write(pin1,gpio.LOW)
    adcv = adc.read(0)
    gpio.write(pin1,gpio.HIGH)
    outv = adcv/ 1024 * 5
    ugm3 = (outv - 0.9) / 5 * 1000
    if (ugm3 >= 0 and ugm3 <= 35) then
	    aqiL = 0
	    aqiH = 50
	    bpL = 0
	    bpH = 35
		aqi = (aqiH - aqiL) / (bpH - bpL) * (ugm3 - bpL) + aqiL
	elseif (ugm3 > 35 and ugm3 <= 75) then
	    aqiL = 50
	    aqiH = 100
	    bpL = 35
	    bpH = 75
		aqi = (aqiH - aqiL) / (bpH - bpL) * (ugm3 - bpL) + aqiL
	elseif (ugm3 > 75 and ugm3 <= 115) then
	    aqiL = 100
	    aqiH = 150
	    bpL = 75
	    bpH = 115
	    aqi = (aqiH - aqiL) / (bpH - bpL) * (ugm3 - bpL) + aqiL
	elseif (ugm3 > 115 and ugm3 <= 150) then
	    aqiL = 150
	    aqiH = 200
	    bpL = 115
	    bpH = 150
	    aqi = (aqiH - aqiL) / (bpH - bpL) * (ugm3 - bpL) + aqiL
	elseif (ugm3 > 150 and ugm3 <= 250) then
	    aqiL = 200
	    aqiH = 300
	    bpL = 150
	    bpH = 250
	    aqi = (aqiH - aqiL) / (bpH - bpL) * (ugm3 - bpL) + aqiL
	elseif (ugm3 > 250 and ugm3 <= 350) then
	    aqiL = 300
	    aqiH = 400
	    bpL = 250
	    bpH = 350
	    aqi = (aqiH - aqiL) / (bpH - bpL) * (ugm3 - bpL) + aqiL
	elseif (ugm3 > 350) then
	    aqiL = 400
	    aqiH = 500
	    bpL = 350
	    bpH = 500
	    aqi = (aqiH - aqiL) / (bpH - bpL) * (ugm3 - bpL) + aqiL
	else
		aqi = 0
	end
	print(aqi)
end)

其中adcv/ 1024 * 5和(outv - 0.9) / 5 * 1000为1024级采样精度转换为电压和相应电压下的粉尘浓度换算,具体可以查阅datasheet得到。如果换算后为负数,即可认为浓度太低检测不到。

下方的aqi换算公式为国家标准环境空气质量指数(AQI)技术规定(试行)( HJ 633—2012 2016-01-01实施)。

实际运行时发现数据不稳定,时有时无。查阅资料发现LED开启过程中有一个上升期。当LED开启持续0.28ms时,对输出电压进行采样最为准确。而NodeMCU的elua脚本并不支持微秒级别的延时。于是考虑其他方法。

查阅资料发现在不更换其他芯片单片机的情况下,ESP8266这块芯片可以采用Arduino的IDE进行C语言程序的编写。下一篇文章会具体写一下如何采用Arduino IDE环境对ESP8266进行编程。