杭马破四随记

作为一个月跑量不到100的佛系跑者本身对成绩没有太大追求,偶尔也想试试自己的极限在哪。年初的湘湖半马跑了1小时52分,跑完后感觉应当还可以更快一些,当时就想或许可以试试全马破四。在杭马中签后决定将破四点想法付诸现实。

如愿破四,03:57:26 完赛。可能以我现在的能力,破四还是有些勉强。这次的全马明显比之前跑过的两次要累很多,特别是最后一公里,感觉随时都有可能抽筋。如果追求成绩,全马确实对身体很不友好。以后应当不跑全马了,即使跑也是完全不追求成绩的吃逛模式。

破四的配速为5分40秒。对于一般的业余跑者无法跑出完美线路,加上GPS误差,大概需要5分35秒的表显配速才能破四。计划前37公里保持5分35秒配速,最后5公里根据身体状态适当调整配速。实际操作过程中实际配速必须快于5:30才能将进水站、上厕所花费的时间追回。

补给方面自己准备了3个能量胶。比赛开始前30分钟吃一条,8公里/16公里各一条。为了充分补给,几乎每个水站都进。补给策略是以运动饮料为主,在补给香蕉、盐丸、能量胶后适当补充一些纯水。

尽管已经充分补给,在过了30公里后依旧会有明显的疲劳感。最后5公里已经没力气拿出手机拍照,就想着快点跑完。最后一公里开始感觉有些不太对劲,随时都有可能会抽筋,停下来稍做拉伸后才好些。

最终如愿破四,03:57:26 完赛,表显配速 5:36 。相比破四的喜悦,更多的还是疲倦。跑步是为了健康,成绩只是微不足道的副产品。

我的玩具之手电筒篇

我手上的几个手电筒。入手价都在 ¥100~¥200。

月亮湖

我的第一支手电筒是2009年入的月亮湖。当时这只手电算是比较热门的手电之一,据说是当时最小的18650手电筒。目前这只手电还在卖,更新了灯珠还出了几个衍生版本。

我的这只应当是初版,整只手电筒非常小巧简洁,上面甚至连LOGO都没有。

务本E7

务本E7 是去年比较热门的一个拐角手电,支持直充带磁吸,可变身成头灯。我买来主要当头灯用。而且根据评测这个手电用的P9灯珠有着非常好的光效。

在路上M9-2

早前买的月亮湖虽然工作正常,但比较年代久远,亮度和光效都远不及新出的手电筒。另外月亮湖不支持直冲,还得多带一个充电器。

两个手电毕竟相差了十多年,相比月亮湖 M9 在亮度和光效上都远超月亮湖,另外还支持直充。可能是多了直充的缘故,虽然都是18650手电,M9相比月亮湖要大上一圈。

选择这个手电很重要的一个原因是这是一只尾按手电。通常侧按开关为电子开关,如果长期不用需要将电池取出,不然会持续耗电损坏电池。尾按是物理通断,不存在这个问题。

中国历年人口变化

中学课本里说生产力决定生产关系。很多社会问题寻根溯源都和生产力相关。劳动力作为生产力中的重要一环深刻的影响了社会和经济的发展。

在网上收集了一些中国的人口数据,做了一个人口变化的统计图表。近年来出现了不少使用 Python 实现前端 Web 界面的工具。这次的图表使用 plotly 实现,使用 Python 做数据处理,并输出 html 图表。

项目地址: https://github.com/vicalloy/china-population
在线查看图表: https://vicalloy.github.io/china-population/

数据分析

  1. 出生人口中 2016 年到达2000年后的高点,之后出生人口断崖式下降。
  2. 2022 年首次出现死亡人口大于出生人口,人口出现负增长。
  3. 将 20 ~ 60 岁作为劳动力。也是在 2022 年首次出现劳动力的负增长,之后还将一直持。注:养老金压力山大。
  4. 2024 年幼儿园的入学人数掉的非常厉害,再过几年就蔓延到小学了。
  5. 2022 年高考录取人数为 1000 万,预计之后较长一段时间都将维持在 1000 万左右。

一些预测

  1. 接下来几年幼儿园因缺少生源,要关停一批。
  2. 生源不足问题逐步蔓延到小学。
  3. 学区房地位下降,成为房价下跌的主力。学区房快速下跌的窗口期没几年了。

京东云亚瑟路由器TTL刷u-boot升级iStoreOS固件

不知道是否为了区分高低端,现在带 USB 口的路由器几乎没有低于 ¥500 的。考虑到以后可以折腾一下把路由器当 NAS,入了京东云的亚瑟。入了后才知道这东西专为 PCDN 而生,想当个正经的路由器用小问题不少。

因为家里有小朋友,定时断网是必须功能,不想这货居然没有。好在我的这个路由器版本比较老,轻松开启 SSH,经过一整折腾后搞定了定时断网。不想好景不长,路由器在关闭自动升级的情况下给升级到了最新固件。路由器上自己加的东西全部丢失,并且 SSH 后门方法失效。这个路由器要想继续折腾只剩下 TTL 刷机一条路。好在这台路由器的 TTL 刷机方案比较成熟,网上也能找到对应的固件。

刷机过程整体比较简单,但由于缺乏经验,中间走了不少弯路折腾了几天才搞定。下面是一个简单的记录,希望对同样的刷机小白有些帮助。

拆机

  1. 撕开路由器底部胶垫,露出底部的5颗螺丝。用螺丝刀全部拧开。
  2. 路由器顶盖使用卡扣固定。敲开后可以看到顶部还有两个固定螺丝,拧开。注:网上很多拆机教程里没有提到这两颗螺丝,导致折腾很久都没能弄开。
  3. 用力挤压路由器筒壁,使网口缩进外壳。抽出路由器本体完成拆机。

搞定TTL接口

  1. 可以看到主板上4个并排的孔V R T G就是TTL接口。
  2. 去淘宝搜 TTL 探针,用的时候直接插到孔上。
    • 焊接的针脚会抵住外壳导致无法塞回去,到时候还要去掉。
  3. 到网上买个 CH340 的 USB 转串口的转接卡。
  4. 我的转接卡上有 3v 和 5v 的跳线,短接 3v 。
  5. 转接卡和路由器接线时注意:G-G,R-T,T-R 这样接。V不用接。
    • G:接地
    • R:接收
    • T:发送
  6. windows系统没有自带 CH340 的驱动,要去网上找个驱动安上。

刷入 u-boot

  1. 串口转接卡一头连好路由器,另一头插入电脑。
  2. 用网线连接路由器和电脑,并将电脑的 IP 设置为 192.168.10.1
  3. 在电脑的设备管理器中查看转接卡对应的串口名。
  4. putty 连接串口,波特用 15200
  5. 路由器开机,按回车进入 6018# 模式。此时已经可以使用 boot loader 的命令了。
  6. 将 u-boot.mbn 复制到 Tftpd64 同一目录。启动 Tftpd64 。
  7. 中 putty 里敲入如下命令完成刷机
    • tftpboot u-boot.mbn && flash 0:APPSBL && flash 0:APPSBL_1
  8. 看到命令输出里有几个 `OK` 就完成 u-boot 刷机了。

准备 iStoreOS 固件

iStoreOS 是基于 OpenWRT 的一个路由器固件。固件可以从 https://fw.koolcenter.com/Lean/JDC_AX1800_Pro/ 下载到。我们需要下载其中的 *-kernel-rootfs.rar 固件。解压后会有两个 bin 文件。需要使用使用工具将两个文件合并成一个 bin 文件后一起刷入。合并工具可以使用 UBin 。由于没有找到软件的官网,大家还是自行搜索下载吧。

刷入 iStoreOS 固件

  1. 将电脑 IP 设置为 192.168.1.2
  2. 重启路由器并用 putty 重新连接路由器进入 6018# 模式。
  3. 输入命令 httpd 192.168.1.1 启动刷机的 web 服务。
    • 看网上的教程,我以为 u-boot 启动的时候会自动启动刷机的 web 服务。在 u-boot 的 help 里看到 httpd 才知道刷机服务要手动启动。
  4. 使用浏览器打开网页 http://192.168.1.1 进入刷机的 web 界面。
  5. 上传固件开始刷机。刷机成功后会路由器会自动重启。路由器启动后路由器灯为绿色。
  6. 用浏览器重新打开 http://192.168.1.1 ,此时已经可以看到 iStoreOS 的登录界面了。
    • 默认用户名为 root ,密码 password

安装Docker

我使用的 iStoreOS 固件并未集成 Docker 。尝试使用 is-opkg install docker dockerd docker-compose 安装 Docer 套件,提示空间不足,无法安装。查看磁盘信息, Overlay 分区只有几M,几乎无法安装任何东西。查看分区信息, mmcblk0p25 分区有 300M 空间。将 mmcblk0p25 分区里的数据删除,并将 /overlay 数据复制过来。在 iStoreOS 的 挂载点 中将 mmcblk0p25 挂载到 /overlay 。应用并重启路由器后可以看到 /overlay 的空间已经变成 300M 里。

安装好 Docker 后,/overlay 还能剩下大概 27M 的空间,几乎没有空间安装其他软件。考虑到其他软件都会使用 Docker 安装,因此暂不打算对 /overlay 做扩容了。

Vim下Python(Poetry)环境的设置

近期迁移到了 Neovim 。在 Pyright 的加持下,vim的代码补全和错误校验功能已经很接近 IDE 了。在未正确配置 Python 环境的情况下打开 Python 项目,项目里一堆的告警让人很不舒服。

在 vim 中编辑 Python,重要的是 PYTHONPATH 的设置。正确设置 PYTHONPATH 后,Pyright 可以正确的查找到相关的依赖库。我目前的解决方案是使用 direnv

编辑 direnv 通用配置,添加 poetry 初始化函数。

vim $HOME/.direnvrc
layout_poetry() {
  if [[ ! -f pyproject.toml ]]; then
    log_error 'No pyproject.toml found.  Use `poetry new` or `poetry init` to create one first.'
    exit 2
  fi

  local VENV=$(dirname $(poetry run which python))
  export VIRTUAL_ENV=$(echo "$VENV" | rev | cut -d'/' -f2- | rev)
  export POETRY_ACTIVE=1
  PATH_add "$VENV"
}

在 python 项目中添加 direnv 设置

vim .envrc
# 进入 Poetry 环境
layout_poetry
# 设置 PYTHONPATH
export PYTHONPATH="`pwd`/vendor/Model1:`pwd`/vendor/Model2"

在设置好 direnv 后,在 CLI 下进入目录时将设置好环境变量。CLI 下进入对应的项目目录,然后启动 vim/neovim ,Pyright即可正确的找到相关依赖。

参考:

从Vim切换到Neovim

vim作者的离世,让vim的后续发展存在很大的不确定性。加上现在用的vim配置一直有些小问题,其中一些插件的活跃度不够,bug一直无法修复。

近期花了些时间把neovim配置好,从vim切换到neovim。

配置文件: https://github.com/vicalloy/dotfiles/blob/master/.config/nvim/init.lua

  1. 没有使用别人配置好的环境,完全自行配置。
    • 之前也热衷于使用流行的集成配置。实际下来发现不管多受欢迎的配置都会有些不符合自己喜欢的地方。而且一旦遇到问题,很难定位问题。而且现在的插件管理机制已经很完善了,自行配置的门槛低了很多。
    • 不少优秀的vim插件都转由lua实现,只能在Neovim中使用。
  2. GUI界面用的 Neovide 。用 Rust 实现的 Neovim 前端。

使用Docker在Orange Pi上LLM(使用GPU加速)

最初买 Orange Pi 5 的目的之一就是想跑一些 AI 应用。Orange Pi 5 虽带了 NPU,但这颗 NPU 实在太小众,除了官方的 Demo 就没法轻松把 NPU 用起来。近期看到有人用 RK3588 跑LLM,于是把吃灰已久的 Orange Pi 5 拿出来折腾。

Orange Pi 5 使用的是 RK3588 芯片,该芯片配备的 GPU 是 Mali-G610。在 Orange Pi 5 上跑 LLM 用的就是这颗 GPU 。

基本用法

LLM 模型通过 MLC LLM 项目加载运行。在 Orange Pi 5 上通过 OpenCL 实现 GPU 加速,因此要求系统支持 OpenCL 。Orange Pi 5 的官方 Linux 镜像已添加了 OpenCL 支持,因此不用再额外安装驱动。

如果 Orange Pi 5 上已经安装了 Docker 可以使用下面的命令把服务跑起来。7b-f16 的模型会用到 6.xG 的内存,如果你的系统只有4G内存可以试试 3b-f16 的模型。

# 更多镜像见 https://hub.docker.com/r/vicalloy/mlc-llm-rk3588/tags
docker run --rm -it --privileged \
    vicalloy/mlc-llm-rk3588:FlagAlpha-Llama2-Chinese-7b-Chat-q4f16_1

编译自己的Docker镜像

rock5-toolchain 项目中提供了 MLC LLMDockerfile ,可以通过修改 Dockerfile 里的 ARG MODEL 来打包不同的模型。

为了更方便的打包不同的模型,更为了白嫖 Github Actions 服务器,我参考 rock5-toolchain 项目写了自己的 Dockerfile。相比原始的 Dockerfile,我把TVM编译/G610驱动安装等步骤打包在镜像 vicalloy/mlc-llm-rk3588:base 预置 model 的镜像从该镜像继承。要预置不同的模型,只要将对应的模型复制到镜像就好。

对应项目地址:https://github.com/vicalloy/docker-images/tree/main/mlc-llm-rk3588

参考链接:

京东云无线宝(OpenWrt)控制终端定时断网

最近将家里的路由器从 小米 换成了 京东云无线宝 。换完后发现新路由器不支持设备的定时断网了。对于有小朋友的家庭,定时断网可以很好的帮助小朋友控制上网时间。好在新入的这款路由器基于 OpenWrt 开发,经过几天的研究,顺利的搞定了定时断网功能。

开启路由器的SSH

注:2023-10 近期路由器被自动升级了。网上的开门方法全部失效,只能尝试TTL开门了。

开始折腾的第一步是搞定路由器的SSH。SSH登录到路由器后就可以随意折腾了。

由于京东云官方的封堵,不同版本固件的SSH开启方式有所不同。

  1. 1.5.40r2181<= 郑羊羊咩的窝-京东云
  2. r2262< 京东云无线宝r2262之前固件版本开SSH
  3. r2279< 京东云无线宝升级r2262固件后打开SSH

我拿到的这台路由器的固件版本很老,直接采用第一个方法开启SSH。具体方法如下:

登录京东云,打开f12控制台,将下面的代码贴入浏览器控制台并运行。

$.ajax({
    url: "/jdcapi",
    async: false,
    data: JSON.stringify({
        jsonrpc: "2.0",
        id: 1,
        method: "call",
        params: [
            $.cookie("sessionid"),
            "service",
            "set",
            {
                "name": "dropbear",
                "instances": {"instance1": {"command": ["/usr/sbin/dropbear"]}}
            }
        ]
    }),
    dataType: "json",
    type: "POST"
})

设备定时断网方案

OpenWrt系统通常自带 web 管理界面 LuCI ,即使没带也可自行安装。如果有 LuCI ,通过 LuCI 丰富的插件系统,可以轻松的实现上网时间的管控。

京东的这款路由器毕竟不是完整的OpenWrt系统,无法直接安装 LuCI 。为了设备的稳定性,保险起见没有继续折腾 LuCI 。研究后发现京东云路由器的自带的黑明单功能是通过修改设备 /etc/config/wireless 配置文件实现,于是有了下面的方案。

  1. 使用 uci 命令修改 wireless 配置文件,将需要管控的设备加入/移出 Wi-Fi 黑明单。
  2. 使用 crontab 创建定时任务,实现定时控制。
  3. 在路由器的黑明单中无法查看到通过修改 wireless 加入黑明单的设备。但可以通过将设备加入黑名单再移除的方式对设备进行临时解禁。

具体操作步骤

登录路由器

开始路由器的 SSH 登录功能,使用 SSH 客户端登录路由器。用户名为 root ,密码为路由器的管理密码。

ssh root@jdcloudwifi.com

创建将设备加入黑明单的相关脚本

1. 创建目录 /scripts 。我们自己的脚本都将放到该目录。

mkdir -p /scripts 
cd /scripts

2. 将下列脚本复制到 /scripts 目录,并使用命令 chmod +x /scripts/*.sh 为脚本添加可执行权限。

disable-wifi.sh

#!/bin/sh
# 禁止设备连接 Wi-Fi
# 使用 `cat /etc/config/wireless` 查看无线配置。通过 `option ssid` 找到对应的 Wi-Fi 配置项名称。注: 2.4G 和 5G 两个热点都需要配置。 
uci add_list wireless.ath0.maclist="$1"
uci add_list wireless.ath1.maclist="$1"
uci commit wireless
wifi reload

enable-wifi.sh

#!/bin/sh
# 允许设备连接 Wi-Fi
uci del_list wireless.ath0.maclist="$1"
uci del_list wireless.ath1.maclist="$1"
uci commit wireless
wifi reload

disable-tv.sh

#!/bin/sh
# 将 dd:dd:dd:dd:dd:dd 换成需要加入黑名单的设备的 MAC 地址
/scripts/disable-wifi.sh dd:dd:dd:dd:dd:dd

enable-tv.sh

#!/bin/sh
/scripts/enable-wifi.sh dd:dd:dd:dd:dd:dd

3. 执行 crontab -e 编辑系统定时任务。

# 周一到周五,8点关闭电视网络
0 8 * * 1-5 /scripts/disable-tv.sh
# 周一到周五,18点开启电视网络
0 18 * * 1-5 /scripts/enable-tv.sh

九寨沟-若尔盖-四姑娘山

考虑到直飞九寨沟的机票较贵,开车从成都到九寨沟时间又太长,最终选择了飞到九寨沟,再从九寨沟自驾回成都。
相比走环线,异地还车可以节约不少时间,加上减免了异地还车费用,算是个不错的选择。

杭州->成都->黄龙->九寨沟

雨季的九寨沟,天气难料。由于天气原因,一直无法确定飞机的起飞时间。最后晚点3个小时,后半夜到达黄龙机场。

黄龙机场修建在山上,海拔3447。最近的住宿点在12公里外的镇上。深夜到达早过了取车时间,花¥80打车到川主寺镇住宿,第二天又花¥60打车回机场取车。

机场附近有大片的薰衣草,如果时间充足,可以留些时间赏花。

黄龙->九寨沟

第二天一早取车自驾到九寨沟。

九寨沟很美。不过或许是因为对九寨沟有着过高的期待,并没有惊艳。

九寨沟->若尔盖->红原

刚出发的一段沿着河谷行走,两旁是陡峭的崖壁,偶有塌方的痕迹。感谢遇上了个好天气,要是遇上雨天,想必会挺危险。

用手机测了一下九若山垭口的海拔3988。一路的盘山公路。不知是高反还是晕车,车上的一大一小都给晃吐了,以至路上的风景都无心欣赏。

翻过垭口,开始进入若尔盖草原。初夏或许是草原最美的季节,草很绿,上面还开着各色的野花。

红原算是一路上比较大的镇子,镇上停车方便住宿条件还不错,价格也便宜。

红原->四姑娘山->理县

四姑娘山景区主要有三个沟可以游览。出发前还想着要选哪个,回头查了一下才知道根本就没得选。除了毕棚沟,另外两个沟都在四姑娘山的另外一面,要多开好几个小时才能到。

在看过雨崩和亚丁稻城的雪山后,四姑娘山的雪山真的太普通了。水不够漂亮,山上的雪很少,可接近性也不行,到不了雪线。四姑娘山唯一的优点可能就是离成都比较近。

晚上住在理县。理县处于两山峡谷间,土地非常珍贵,导致几乎找不到停车位。即使是酒店也只能提供非常有限的停车位。

理县->成都->杭州

初夏的成都已经很热了,不适合出游。在成都人民公园简单的转了一下就直接出发去机场了。市区严重堵车,驾驶体验非常不好。

Magpie 股价价格提醒工具

项目地址:https://github.com/vicalloy/magpie/

股票工具。设置股票的止损点和营收点,在到达止损点或营收点时发起消息推送。提供一个简易点web服务器用于查看相关股票的当前价格。

注:

用法

编辑规则文件

提醒规则使用 Json 格式进行描述。编辑规则并保存为文件 rule.json 。

[
  {
    "stock_code": "sh000001",
    "stock_name": "上证指数",
    "base_price": 3200,  # 基准价格,用于计算涨幅
    "alarm_price_min": 3100,  # 止损点
    "alarm_price_max": 3400  # 营收点
  },
  {
    "stock_code": "sz000333",
    "stock_name": "美的",
    "base_price": 54,
    "alarm_percentage_min": 0.15,  # 止损点 base_price * (1 - alarm_percentage_min)
    "alarm_percentage_max": 0.15  # 营收点 base_price * (1 + alarm_percentage_max)
  },
]

启动 Web 服务器

docker run --rm \
    -v `pwd`/rules.json:/app/rules.json \
    -p 8000:8000 vicalloy/magpie:latest \
    python -m magpie server -r ./rules.json

在浏览器中访问网址 http://localhost:8000/ 。

检查股价

docker run --rm \
    -v `pwd`/rules.json:/app/rules.json \
    magpie:latest \
    python -m magpie check -r ./rules.json \
    --datasource qq \
    --bark-token $(bark-token) \
    --tg-token $(tg-token) \
    --tg-chat-id $(tg-chat-id)

可以通过设置 crontab 的方式定时执行股价的检查。

备注

10 9,10,11,12,13,14 * * * sudo docker run ....