MoreRSS

site iconDarksair修改

在肯塔基大学攻读理论物理学,专攻高性能计算、数据分析、数据可视化、编程、数字设计等领域。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

Darksair的 RSS 预览

联邦宇宙历险记

2022-12-27 13:15:00

介绍

最近马一龙老板在 Twitter 搞了一系列事情,炒红了「联邦宇宙」这个概念,很多推友都申请了帐号。我一开始是拒绝的,因为我不怎么看好这个东西。分布式服务里用户最多的当属 email,可以说是失败的典型了⸺email 现在的状态可以说和「分布式」一点关系都没有,我认为这是所有分布式服务足够流行以后的必然归宿。但是后来马老板的政策过于光怪陆离,基本上是逼着我开始考虑其他平台了。

「联邦宇宙」这个词听起来神神叨叨的,其实它就是指网上有一票服务器,它们都使用同一个协议互相发消息,这个消息可以是一段文本(micro-blog),可以是图片(类 instagram 服务),也可以是视频(Peertube),而这个协议就是 ActivityPub。如果你注意看这个链接就会发现⋯⋯没错,这是个 W3C recommendation~~ 既然有协议,就要有实现这个协议的软件,其中最流行的当然就是现在烂大街的 Mastodon。本着「流行的一定不是最好的」的原则,我选择了比较小众的 Pleroma⋯⋯我在家里有自己的服务器硬件和环境,其中开了数个虚拟机,所以我直接就装在其中一台虚拟机上了。Pleroma 有官方编译好的二进制版本,可以直接运行,没有其它运行上的依赖,所以架起来十分简单,直接跟着官方文档走就可以了。我的虚拟机用的是 Arch Linux,所以用了 AUR(后来我自己升级到了 2.5)。整个安装过程用 Ansible 自动化,目前为止还比较无痛。

坑,好大一个

但是目前 Pleroma 有个惊天神坑,就是它对于「用户 ID 域名和服务域名不一样」这件事的支持。这要从 WebFinger 说起,WebFinger 的逻辑是这样的:你有个域名,很短很好看,你想用这个域名作为你 ID 的一部分,我们暂且把这个叫做你的公开域名。但是你想挂很多 HTTP 服务,每个服务都有自己的入口,一般这种情况有两种做法,

  • 所有的服务都挂在公开域名下面,但是在不同的路径下,比如 blog 在 /blog 下,Wiki 在 /wiki 下,等等。这种方法有很大的局限性,比如有些服务可能就不支持挂在非根路径下面;如果在根路径下挂服务还要保证 URI 不能重。

  • 在公开域名下开子域名,把服务挂在子域名下,在 HTTP 服务器里给每个子域名开虚拟服务器。这是比较好的做法。这里暂且把这个子域名叫做内部域名。

我家里的网络本来就在一个内部域名下面,所以我肯定是选择第二种方法,更何况 Pleroma 压根就不支持第一种方法。那么问题来了:内部域名很长,我就想用公开域名作为 ID,但是在内部域名下面架服务,怎么办呢?这里就需要一种机制,当外面看到我的 ID,认为我的服务在公开域名下,但是公开域名里有个东西告诉对方,我的服务其实是在内部域名下,让对方去那找。WebFinger 就是这样一种机制。Pleroma 用到的 WebFinger 其实是两个协议:

  • Web Host Metadata(RFC6415),这个协议说的是当外面想访问一个域名下的某个资源的时候,这个域名可以告诉对方关于这个资源的元信息。协议规定支持这个协议的程序在访问一个资源的时候,会先访问 /.well-known/host-meta 这个 URI,如果服务也支持这个协议,应该返回一个 XRD 文档。

  • WebFinger(RFC7033),这个协议说的是如何在一个服务里找一个人。

Host-meta

在 Pleroma 的语境下,这两个协议的用法是这样的: 每个人有自己的 ID,公开域名是这个 ID 的一部分。这个 ID 就是这个服务里的一个资源。所以如果有人想找到我,这个人应该先访问 host-meta,注意这时外面并不知道内部域名的存在,所以访问的是公开域名下的 /.well-known/host-meta。这时应该返回下面这个 XRD 文档:

<?xml version="1.0" encoding="UTF-8"?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
  <Link rel="lrdd" template="https://internal.domain/.well-known/webfinger?resource={uri}" type="application/xrd+xml" />
</XRD>

简单地说这个文档的意思是你要找人的话就去这里看 WebFinger,其它的事我不管。LRDD link 是另一个 RFC,里面的 {uri} 就是要找的人的 ID(包含公有域名)。

注意这个请求发生在公有域名,所以 Pleroma 是看不到的。所以这时有两种方法:

  • 把这个请求重定向到内部域名,让 Pleroma 处理,这个 Pleroma 是支持的。

  • 这个文档是不用变的,所以可以手动在公有域名的目录里创建这个文件,或者把文件内容直接写在 HTTP 服务器的配置里。

对面在收到这个文档以后应该去访问里面提供的这个 URL,也就是 WebFinger 请求。

WebFinger

这时对面其实就已经知道了服务是在内部域名下。//internal.domain/.well-known/webfinger 这个 URL 完全是 Pleroma 负责的,回应里会包括用户的 profile URL(当然是内部域名)。如果 Pleroma 的版本是 2.4 或更老,这里还有一个二阶神坑。前面说到 host-meta 的回应里有 webfinger 的 URL,其中包括一个 {uri} 变量。对面看到这个以后应该把这个 {uri} 替换为用户的 ID,然后去访问 URL。所以整个 WebFinger URL 是 https://internal.domain/.well-known/[email protected]。但是在 2.4 或更老的版本里,这个 URL 会返回 404,因为 Pleroma 期望对面会把这个 {uri} 替换为使用内部域名的 ID⋯⋯这根本就不对,也没有其它实现会这样干。所以当时我在 Apache proxy 里有几个重写规则来处理这个事:

RewriteCond %{REQUEST_URI} "/.well-known/webfinger"
RewriteCond %{QUERY_STRING} "resource=acct:(.*)@public.domain"
RewriteRule ^ "http://127.0.0.1:1234/.well-known/webfinger?resource=acct:%[email protected]**?**" [P,L]

RewriteCond %{REQUEST_URI} "/.well-known/webfinger"
RewriteCond %{QUERY_STRING} "resource=acct%3A(.*)%40public.domain"
RewriteRule ^ "http://127.0.0.1:1234/.well-known/webfinger?resource=acct:%[email protected]**?**" [P,L]

在 2.5 版里已经修复了这个 bug。

到此为止,整个查询用户 ID 的流程就完成了,Pleroma 对这个流程的实现是没有问题的。但是我觉得官方根本就没有想明白为什么要来这么一套复杂的逻辑⸺是为了可以让用户声称自己的 ID 就是在公开域名之下,别人看到的 ID 和别人搜索这个用户时使用的 ID 都应该使用公开域名!而你在 Pleroma 和 HTTP 服务器里设置好这一切以后(官方甚至专门有文档教你设置),Pleroma 依然傻了吧唧在网站上显示用户的内部域名 ID,别人用公开域名也找不到你。这样 WebFinger 的意义何在?

解决办法

理论上这个坑是可以填的,我想的一个办法就是把公有域名下的 HTTP 服务器当作 proxy,这样外面看来服务就在公开域名之下,完全看不到内部域名。但是这个方法对我不可行,因为我的公开域名解析到外面的 VPS,内部域名解析到家里,中间的网络延迟不可忽略。当然另一个方法就是抛弃 Pleroma,使用其它实现,比如

  • Mastodon,其实我一开始是准备架这个的,但是我折腾了一个星期都没架起来,总是有各种错误,弃疗。

  • Misskey,JavaScript 写的,不考虑。

  • GoToSocial,有可能会换到这个,但是似乎功能不多,尚处于开发的早期阶段。

除此以外我也只能等官方修了。等我其它玩具项目写完以后可能会自己写一个 ActivityPub 实现。

一些想法

本文最开始说了,我对联邦宇宙这个东西是不看好的。这里的「不看好」并不是说这个东西不好用(虽然现在确实没有很好用⋯⋯),而是我认为所有这种 federated 分布式服务最后都会是两个结局中的一个⸺要么用的人很多,成为事实上的中心化系统;要么没什么人用,成为少数 geek 的玩具。前者的例子是 email,后者的例子⋯⋯是所有其它分布式服务。这个趋势在我看来是必然的,用户多起来以后必然就会有大公司想来分一杯羹,它会搞出一套特别好用(至少是看起来好用)的实现吸引用户。而这些用户里必然只有极少数是真正关心「分布式」这件事的,大部分人都只是想找个方便且稳定的服务,以及别人用什么自己就用什么。大公司的用户多起来以后就要留住用户,这里的方法之一就是以安全为名强行把标准拉高,然后拒绝与不够标准的实现(也就是其它所有实现)互通。

这套伎俩不仅用在了 email 上,还用在另一个受众更广的协议/实现上,那就是 HTTP 和浏览器,具体来说就是拔高 SSL 的标准,并且强行在浏览器里引入证书。

不知道你知道不知道,现在的浏览器都认为如果你的 SSL 证书有效期多于一年,那就是不安全的。Excuse you?? 我自己在家里的网络上,外面又访问不到,给自己开一个有效期十年的证书,不行吗??你算什么东西?告诉我我自己的证书不安全??关你屁事啊??这也太把自己当人了吧??要是真想安全的话你咋不要求每个 session 都新开个证书啊??

另外在浏览器(和操作系统)里默认自带一套证书这件事,实在是太过虚伪。大家都知道 SSL 证书的信任关系是树状的,最后总会追溯到少数几个根证书上。这里的逻辑是这些根证书是由一些比较「权威」的公司颁发的,其它人如果想要证书的话,要向这些公司(以及他们信任的其它机构)申请,证明你是你,你妈是你妈,你祖宗十八代是你祖宗十八代,这些公司验证过后,就会颁发证书。问题是这种破事你们几个公司之间玩玩就算了,不就是花钱买信任么?不新鲜。你信任他,那是你的事,跟我没关系,但是你把这些证书放到浏览器里,让所有用户默认信任,这算什么道理?我又不认识你们,凭什么信任你们?你们又没给我钱对不对?这也太把自己当人了吧?我认为这里正确的做法是浏览器默认不信任任何证书,但是能访问使用证书的网站(当然要是真想安全的话应该连访问都不让访问),地址栏里放个叹号(说真的,反正又没人 care,放了就放了),让用户选择信任哪些证书。

当然有人说了,这些大公司都是有一定公信力的,他们旗下的证书都是他们验证过的,确实它是它,它妈是它妈,值得信赖。那请问 Let’s Encrypt 是怎么回事?我开 Let’s Encrypt 的时候怎么没人验证我是我我妈是我妈?Let’s Encrypt 的 HTTP 验证本身就是不安全的,怎么不说了?所以就不要假模假式地搞这些事了,何必呢对不对~~

扯远了,回到分布式服务这件事上。这里的矛盾其实是少数 geek 和大多数小白之间的人民内部矛盾。少数 geek 的需求是分布式,去中心化,这就必然意味着鼓励每个人(或者至少每个小团体)搭建自己的服务,这和其它大部分人的需求是完全相反的。此外还有另一个问题,就是分布式的协议设计和实现都比中心化的要复杂,所以对社区的要求更高。我忘了是在哪里看到的了,Matrix 的设计者和 Signal 的大佬(Jabber 的大佬?)吵架,Signal 大佬说你们这样是不行的,分布式太难做了,你们成功不了。Matrix 大佬回答说这就是为什么我们要做。

当然现在 Matrix 的实现和客户端确实没几个好用的就是了,就像 Fediverse 一样。

Xenoblade 3 玩后感(剧透)

2022-08-22 16:33:00

历时 65 小时,我终于把《印度神剑 3》通关了,目前的时长是 122 小时,总的来说比较失望。剧情和音乐平淡无奇,战斗系统和收集元素比较出彩。这个游戏本质上就是个大号的 fan service,其实根本是没必要存在的,Monolith 可能觉得把前两代的宇宙停掉太可惜了,决定再收割一波。

这里需要说明一下,本文对这个游戏的评价是以《异度之刃》前两代为标准,这是个非常非常非常高的标准。

剧情

这游戏最严重的问题在于剧情非常简单,缺乏深度。整个故事主要就两个矛盾:主角队伍和执政党之间的矛盾,和执政党高层的内部矛盾。这两个矛盾都非常平淡,毫无悬念。主角队伍在游戏中的路径大概是这样的:

  1. 走路

  2. 队长别开枪,是我

  3. 有超能力了

  4. 走路

  5. 走路

  6. 走路

  7. 女主死了!

  8. 女主没死!

  9. 走路

  10. 大 boss 哪里跑!

而 N 的剧情其实就仅限于:

  1. 大 boss:你想吃蓝药还是红药?

  2. N:蓝药!我喜欢蓝色!

  3. N:我错了我错了还是红药好!

整个过程中唯一比较让人投入的地方就是女主死了女主没死那里,由于 Mio 是全队唯一有生存压力的人,而在监狱里编剧非常聪明地把 Mio 和其他人分割,这里的悲剧处理很好地调动了观众的情绪。但是这里其实就彰显了这个游戏剧情的根本问题:由于 fan service 的定位,剧情缺乏悲剧。反观二代,反派队伍不仅人多,而且每个人都充满了悲剧。Jinn 就不说了,他其实是二代本质上的主角。像 Malos 这样一开始疯狗一样的人物,到最后也发现他其实是没有自由意志的,整个行为是由 Amalthus 自带的反人类属性驱动,Malos 在二代正传里的故事其实是一个追寻自我的过程;而 Amalthus 的反人类属性也有其悲剧的来源。这三个人构成了二代悲剧的扛把子,在这个基础上发展出了 Haze 和 Mikhail 等一票有头有尾的悲剧人物,整个结构宏大、精妙且充满深度。

而三代里能撑场面的悲剧人物其实就只有 M 一个,N 由于剧情过于老套和可预测只能算半个⋯⋯

抛开这些,故事本身其实简单地令人发指,主角队伍基本上是一路平步青云杀到大 boss 那里,然后居然就完事了?我当时打到大 boss 的时候还隐隐觉得这游戏应该会转折的吧,大 boss 后面应该还有隐藏的巨 boss 吧?然后发现真的就没有了,Z 真的就是大 boss⋯⋯

说到 Z,这个人简直就是莫名其妙。这个人的来历据游戏里说就是世界上有很多保守人士,由于这些人过于保守,保守观念过于强大,这些观念化成了人形,诞生了 Z⋯⋯哪尼???(咳咳,这一定不是在暗指某些人,嗯。)除此以外,整个世界里也充满了莫名其妙的「人为」设定,比如人只能活十年什么的,为什么不是九年或者十一年?对比一下,二代像是用第一性原理导出的理论,而三代就像是个充满参数的模型(咳咳超对称咳咳⋯⋯)。

最后我想问一下,结尾两个世界分开以后,City 的人怎么样了⋯⋯?

总结一下,这代由于剧情的限制,我认为它只能作为一个 fan service,无法和一代二代并列成为第三代。但是这里有个很可惜的地方,就算这代剧情有诸多缺点,但其实只要把结尾改一下,它不仅能很好地融入前两代的宇宙,还能把全部三代整合并提升为一整个更大的悲剧故事。这里卖个关子,最后再说。

音乐

《异度之刃》这个系列,我觉得剧情、音乐和系统各自贡献三分之一,少一样只能算勉强及格,少两样就废了。二代基本三样都可以满分,战斗系统繁琐了点,但不差;一代剧情我觉的略有欠缺,但同样不差,其他两样满分;三代刚才说了,剧情已经废了,音乐我觉的能给一半分。但这个问题有点复杂,不能单从好听不好听来考虑。

三代的音乐往大了说,有背叛 JRPG 传统的嫌疑。JRPG 的音乐一般有个特点,就是不仅在游戏里好听,单拿出来听也好听,换句话说就是真・好听。不仅《异度之刃》的一代二代是这样,连《仙剑》系列也这样,这几个游戏的音乐都是我音乐库的永久成员。很多时候 JRPG 的音乐过于好听,以至于会喧宾夺主,这也是游戏媒体在评论 JRPG 的时候一个比较常见的评价。

三代的音乐从「好听」这个角度讲,离前两作有很大的距离。具体说,就是这次的音乐都特别平淡,像电梯音乐。即使是剧情转折处的过场动画配乐,也没有像二代 Counterattack 和《君との未来》那样音乐本身跌宕起伏也在讲故事的曲目。《君との未来》在这方面尤其突出,这个曲子其实就是把二代剧情用音乐又讲了一遍,堪称神曲。一代里这样的曲子不多,但是一代音乐的亮点在地图配乐,以 Eryth Sea 的配乐为代表,旋律美轮美奂,优美到令人发指。而且 Monolith 也知道这点,在三代里数次使用 Eryth Sea 的变奏,连片尾曲都是,这也造成了一个很囧的现象:这代里最好听的音乐是前代音乐⋯⋯

但是「平淡」和「不好听」,都不算「背叛 JRPG 传统」,我之所以说「背叛」,逻辑在这里:三代的音乐用的是前两代的原班人马,水平摆在那,前两代的音乐加起来有九张 CD 之多,所以这帮人能作出好听的音乐肯定不是巧合,所以真相只有一个⸺这代音乐做成这样是故意的,很显然,这次音乐的重点由音乐性本身转向了功能性,变成了「氛围音乐」。这次的音乐大多旋律比较简单,配器比较轻,明显是想占据一个背景的位置,让你好好享受这次的巨型地图。对比前代,一代里 Colony 9 的小提琴一响起,我就想放下手柄闭眼听音乐了;而二代里的帝国配乐就不用我多说了吧?前两代是买音乐送游戏,这个说法至少对我来说并不夸张。这代里的音乐是对这个特点的一个很强的背离。顺便说一下,这个趋势其实从二代的 Torna DLC 就开始了。

这代音乐的弱音乐性和强功能性,是我觉得它「背叛 JRPG 传统」的地方,但这没什么错,只是方向变了。我不喜欢,但是我算老几?

其它

前面说了这么多不好的地方,这里说点好的。这代的升级和战斗系统是集前两代(包括 Torna)的集大成之作。一代的主要问题是过于简单,人物就那么几个,重点在装备搭配。打架的时候基本就是几个招轮着用,但是一代有个巨大的亮点:主角的时光机。这个机制的存在让这个简单的系统可以登上异度系列的大雅之堂。二代的战斗系统比一代复杂了很多很多,但同时战斗过程也冗长了很多,这个主要归功于新加的一个机制:挂球⋯⋯在 Torna DLC 里 Monolith 终于找到了正确的节奏,让二代的系统手感轻快了起来。这一代的战斗系统集成了前两代的诸多优点。和二代一样,武器和招式来源于英雄,相当于二代里的 blade。很显然 blade 是个极其成功的设定,但是这一代没有吸收二代的一个败笔⸺抽卡,而改成了剧情驱动英雄解锁,顺带着就取消了二代里鸡肋的 common blade,可以说是把这个系统的精华完全继承了过来。连二代里很成功的 Poppy,这代里也拿过来变成了 Triton。节奏上这代没有使用引出二代里挂球机制的元素设定,而使用了一代的简单系统,还解锁了 chain attack 的伤害上限,让 chain attack 比二代更有可玩性,诞生了打 super boss 的时候砍三两下直接开 chain attack 的流派。

总的来说,这代的升级和战斗系统基本可以说是完美了。

前面说剧情的时候我说了很多的黑点,但这些黑点都是主线剧情上的。这代的支线任务剧情比主线好很多,很多配角在连续的支线任务里都发展得非常丰满。比如 Colony 9 的老大 Zeon,在 Colony 9 的种田任务线最后和 Tau 的一姐 Juniper 结成了扶贫对子。这个任务线做完以后的感觉就是,主角的脸上又增添几道皱纹,但是想到两位老大都各自收获了好吃的土豆,这一切努力都是值得的。我觉得这一代要玩剧情的话,就把主线剧情当作一种解锁支线剧情的机制来玩就好了⋯⋯

最后要把一开始卖的那个关子圆回来。我设想了一个结局,可以很好地把这三作统一成一整个大的悲剧故事,这个结局是这样的:

打完大 boss 以后主角团队,Nia 和 Melia 发现 Z 的死亡解锁了 Origin 的一个不为人所知的机制,可以使得这个世界永久稳定地存在,并且不需要两波人互相打这样的弱智设定,但是代价是主角团队必须死(或者是 Nia 和 Melia 必须死,不重要)。为了保护来之不易的革命成果,主角团队毅然决定牺牲自己。一阵操作之后,Nia 和 Melia 启动了这个机制,世界得救了。

如果你觉得这就是我说的悲剧,那就错了,悲剧在后面。

之后这个世界就这样运行了几百年,当然世界上的人就都是 City 的后代了。这几百年里科技高速发展,人们生活水平飞速提高,农民们用上了彩色电视机、缝纫机、自行车、手表⋯⋯太空上甚至建起了空间站。后来在这个世界上诞生了一个最杰出的科学家,叫 Klaus⋯⋯

change

关于一些学术软件的八卦

2022-03-23 16:21:00

老婆在某大学里管超算,收到一个 ticket 说有人有个 Python + C 的程序出错,段错误,让我看看怎么修。我折腾了一个晚上,发现是 Python 会默认 C 函数的返回值类型是 int,但是那个函数的返回值是个指针,而且在 Python 里拿到返回值以后会传给另一个 C 函数,在我们测试的机器上(超算和我自己的机器)Python 会把那个返回值截断再补上,不段错误就怪了。不过这个修起来很简单,在 Python 里声明返回值类型是指针就好了。但是我修好了以后发现这破程序还有别的恶性 bug,比如 use after free⋯⋯

于是我们让他找作者修,作者是个康奈尔的教授。他说之前找过了,作者坚持说程序是对的,而且他在其他机器上都能跑。当时我就呵呵了,这也太把自己当人了。如果我是用户大概直接 email 就骂过去了⋯⋯

学术圈这样的破程序挺多的,我一直在想为什么这些人就不能好好地写个好程序。我的一个感觉就是除了物理以外其他科都不喜欢搞大 collaboration,都是各干个各的。我用过的物理圈的牛逼程序大多都是 collaboration 搞的,比如 CERN 的 ROOT 和 USQCD 的 Chroma,当然个人写的也有,这些人最后都转码了嗯。

另一个想法是为什么不好好地开源一下让社区写,也相当于搞 collaboration 了,问老婆,老婆说搞不起来,因为这些程序一般没什么人用⋯⋯

关于 collaboration,我又想到了以前在囧乎上和别人的讨论,为什么像生物这样的学科只满足于 p=0.05,做实验就只用几只几十只小白鼠,为什么文章里 error bar 都碰上了还大言不惭地说 significant。比如我之前随便看的一篇关于 Covid 的文章里面有这个图:

significant
Figure 1. 这要是都能算 Significant 天下人都能水 PRL 了……我严重怀疑这人说的 significant 意思是中心值相差多于一倍,他标 significant 的那几组数据都符合,没标的都不符合……Error bar 什么的可能就是个装饰。

有人评论说小白鼠很贵的,我问那为什么不搞 collaboration,有几个人回复说想搞到基因满足某些条件的小白鼠很贵很难而且很难维护什么的。最后我懒得再打字了就说好吧我也不了解情况大概确实很难吧,但其实我白眼都翻到天上去了,难个屁啊,再难能有 LHC 的百分之一难么⋯⋯人家 CERN 几百个人做十年,最后没有五个 sigma 的信号都不敢发文章⋯⋯

所以真的,做事要认真,不然就别占着茅坑不拉屎了,给别人腾腾地儿。

在分子动力学界,有个著名的软件叫 Gaussian,性能特别好,但是是个商业软件,还很贵。不同于其他很多 MD 界的学术软件,这玩意是个「现代」的软件,有文档、安装包、论坛和技术支持。但是这玩意在圈里名声很差,因为这程序最早是一个叫 John Pople 的有志大叔写的自由软件,成型以后让合伙人窃取了,成立了公司也闭源了。这公司跟我国一样,骂不得。你说它不好它就会把你拉到黑名单里让你用不了,所以也有很多人用着其他更奇葩的软件,比如 CHARMM, GROMACS 和 NAMD 什么的。CHARMM 是 Fortran 的,后面两个是 C++ 的,这些功能都 不如 Gaussian 多,所以有时就需要你自己写插件。比如我老婆之前需要撸一个特殊的力场,研究了半天 GROMACS 的 API 都没整明白,我也没时间帮她写,所以最后用了她老板的祖传 Fortran 插件⋯⋯总之,这些科研工作者对 Gaussian 敢怒不敢言。

后来 John Pople 受不了了,从 Gaussian 跑路出来又开始了一个新的 MD 软件 Q-Chem。老婆跟我说 Q-Chem 最初也是自由的,后来又让人窃取了,但是这个就无从考证了。

这件事告诉我们学术圈懂软件工程的人真不怎么多(因为懂的都转码了),不然那些自由软件没什么道理功能跟不上,毕竟数学上都是推好的的,写程序实现一下就好了⋯⋯CHARMM 和 GROMACS 的文档我也看过,感觉还挺全的,各种基础库和结构也都做的不错,扩展起来不难。

说到 CERN,可能很多在圈外的人不知道 CERN 在计算上有多牛逼,其实很多物理圈的也不知道(比如我以前)。我读博的最后一年 LHCb 的人来我校做了个报告,扯了很多 penta-quark 啦 dark matter 啦我都没在意,但他后来讲数据处理的时候我都震精了⋯⋯他说他们有一套自己设计的软硬件用来实时采集和处理 TB/s 级别的实验数据,有专门的超算做实时的 preliminary 分析,实时出结果,而且分析还是带 machine learning 的。我当时作为一个计算狗感觉就是无地自容⋯⋯

所以我转码了。

记一件有意义的事

2021-10-27 20:24:00

水果 CSAM 识别

最近水果出了个事,叫做 CSAM,Child Sexual Abuse Material,简单地说就是儿童色情检测。这是 iOS 15 将要加入的「新」功能(待会儿要说到为什么「新」是加引号的)。消息一开始是泄露出来的,从泄露出来的消息来看,这个系统是这样的:

  • 对于手机里的照片,计算某种 hash,并上传 hash,iCloud 和本地照片都有。

  • 对于匹配的照片进行人工审核。

这年头上传 hash 这件事基本就不是事,涉及到隐私的部分在「人工审核」这里。人工审核肯定不是审核 hash 了,必然要上传照片本身(当然水果并没有说,我猜的)。那么水果凭什么偷偷上传你的照片本片呢?肯定是要在用户协议里偷偷加东西了。

但是!!!

这件事最可怕的点不在这,而是

  • 水果把所有人都当成潜在的儿童色情罪犯。

  • 如果我国要求水果扫描用户的政治性图片并上报怎么办?

后来水果发布了一个 FAQ,并且某高管接受了一个采访,透露出了另外一些信息:

  • 匹配 hash 的过程发生在本地,hash 不上传。而且这个匹配是「非常准确」的。

  • 只匹配 iCloud 上的照片,用户可以通过关闭 iCloud Photo 来 opt-out。

  • 在孩子的 iMessage 里自动识别 18+ 内容。这个家长需要 opt-in。这个和上面那个儿童色情匹配无关,是个独立的功能。

所以至少这些功能是可以关闭的。但是这点很奇怪⋯⋯既然匹配是在本地,为什么不同时也匹配本地非 iCloud 照片?非 iCloud 的儿童色情就不是儿童色情了?水果不关心儿童安全么? 为什么允许 opt-out?Opt-out 的儿童色情就不是儿童色情了?水果不关心儿童安全么?我觉得大概的确是这样,水果只关心自己的云里有没有 CASM,用户本地的照片不是水果的责任。

另外在采访里,记者连续问了三个同样的问题,就是如果政府要求水果识别除儿童色情以外的照片,水果怎么办。水果在第三个问题的时候才稍微沾点边地回答了这个问题:这个功能只在美国启用,在美国的法律框架下政府很难强迫水果加入识别合法内容的功能。那么如果我国政府要求水果加入其他识别功能呢?水果的回答是这样的:

The hash list is built into the operating system, we have one global operating system and don’t have the ability to target updates to individual users and so hash lists will be shared by all users when the system is enabled.

简单地说就是「我们的操作系统是全球统一的,所以我们无法单独为一群人加入某个功能」。

哪尼???你刚刚不是才说了识别儿童色情这个功能只在美国有么???你可以在全球加入这个功能然后只在某国开启啊?????所以实际上水果是承认了他们会在政府的要求下加入其他识别功能。

不过我国人民也不用过于担心,我国有云上贵州,不需要这个功能。

Did someone say “hash”?

既然是 hash,那必然就有碰撞。水果官方说了,每年发生碰撞的概率大概是「万亿分之一」。所以自然发生的碰撞几乎是不可能了?那么有没有可能人工构造碰撞呢?

有大佬发现,在 iOS 14 里其实已经内置了这个匹配功能,并且能导出模型。使用这个模型,另外一些大佬很容易的就构造出了碰撞;还有些大佬构造出的,内容就是这张图的 hash。所以人工构造碰撞不仅可能,而且似乎很简单。这有没有可能是一个攻击的方向呢?我作为安全小白就不知道了。假设有人构造了一个看似无辜的碰撞图,比如看起来是个酷炫的壁纸,发到网上让人下载,会在很多人的手机里触发 CSAM。这种「自然发生」的人工碰撞,概率肯定是要大于万亿分之一的。

另外真・自然发生碰撞概率是不是真的这么低呢?显然这个概率很难估计,但是有人使用导出的模型扫描了 ImageNet,已经发现了两对碰撞(互相碰撞,不是和 CSAM 碰撞)。

「新」功能?

CSAM 这件事本来到这里就没什么好说的了,但是无独有偶,水果正在和 Epic 进行的官司竟然透露出了更多的信息。在这个官司公开的文件中,有水果高管在内部邮件里说了这么几句:

The spotlight at Facebook etc. is all on trust and safety (fake accounts, etc). In privacy, they suck. Our priorities are the inverse. Which is why we are the greatest platform for distributing child porn, etc.

哪尼??水果是最大的儿童色情流通平台???当然这倒不是特别值得惊讶,就算水果不是「最大的」,也肯定是「很大的」,毕竟水果有那么多用户。关键是水果怎么知道自己是最大的儿童色情流通平台?答案当然是:水果扫描用户信息了。的确,在这个邮件公开以后,水果不得不承认,他们从 2019 年就开始扫描用户的邮件中的 CSAM 了。

长期以来水果的卖点一直都是隐私。水果从自研芯片(iPhone 4)开始,基本上所有的技能点都是围绕这个主题展开的。Security enclave,Touch/Face ID,differential privacy 等等这些与隐私密切相关并且水果大书特书的特性,其实归根结底起点都是自研芯片。我们都知道在大概 iPhone 5s 和 iPhone 6 的时候,水果设备的安全性得到了一次巨大的提升。从此以后,FBI 就很难从锁着的 iPhone 里提取数据了,关注这点的同学可能还记得 2016 年 FBI 因为无法破解一个 iPhone,要求水果给操作系统添加后门的,我当时还在囧乎写了一篇文章。水果甚至还在 Black Hat 2016 上做了个报告,来显摆 iPhone 和 iCloud 的安全架构。

但是 CSAM 这件事基本上就相当于重置了水果的这些努力。如果水果也会扫猫用户的照片甚至邮件,Google 也会扫描(其他厂商很早就开始扫描 CSAM 了),那水果在隐私方面还有什么优势呢?

一个违背祖宗的决定

ancestor

大家都知道水果是一个在用户体验设计上高度自负的厂商,同时他们只为主流市场设计体验。这样就形成了一个局面:当水果认定自己的设计对于主流是最佳体验以后,他们就会非常的固执,并且拒绝为非主流用户提供选项,而主流用户确实也非常买账。但是对我来说有个问题⸺我不是主流用户⋯⋯

在 iPhone 上,想从电脑上传音乐文件只能使用 iTunes,这是一个特别古老的设定,古老到乔帮主刚回到水果,发布 iPod 的时代。为什么水果不更新这个古老的设定呢?因为主流用户都去用 streaming 服务了,没有人再想从电脑上上传音乐。但是我想。我有 74 GB 的音乐文件,并且我只听这些音乐;实践证明,只要是我音乐库以外的音乐,我一定不爱听,这 74 GB 就是全宇宙仅有的我爱听的音乐。我为什么还要用 streaming 服务呢?

在 iPhone 上,如果用户想要运行自己写的 app,就必须每年交 $100 成为开发者,否则自己写的程序只能在 iPhone 上运行几天。这是一个安全设定,现在认为对于主流用户,可以随心所欲地运行任何程序是巨大的安全漏洞;事实也确实如此,想想我国有多少个人电脑上装着 360 和百度全家桶,再回忆一下上次的 XcodeGhost。但是我既不是主流用户也不是开发者,我是那种 95% 的时间很正常,剩下 5% 的时间会写点自用 app 的奇怪用户,我才不会为了那 5% 而交 $100 的年费。

水果去掉了 iPhone 上的耳机口,因为水果认为 iPhone 的终极体验就是无线使用 AirPods, it just works™。AirPods 音质不好?主流用户不会在意的,毕竟水果耳塞可能就是他们这辈子听过的音质最好的设备。但是我在意,我买 UM3X 回来不是当摆设的。

因为这些原因,我一直在考虑换成安卓手机,但基本一直是观望。这次 CSAM 事件之后,我终于认真考虑更换了,毕竟就像之前说的,至少在隐私上水果已经没什么优势了。安卓手机的选择很多,我看了一圈评测,最终选中了全宇宙最便宜的 Pixel 4a。

换鸡辣
Figure 1. 换鸡辣~~

违背祖宗后的体验

到目前为止,新手机已经用了两个月,最大的感觉就是在 iOS 上自带的程序在安卓这边都是第三方的。比如听音乐的程序,如果你像我一样只听本地存储的音乐,在 iOS 上基本就只能使用自带的音乐程序,而在安卓这边有很多的选择。这其中根本的原因是 iOS 不开放文件系统,用户没法自由地上传音乐文件。而在安卓上上传音乐,又比用 iTunes 上传方便很多。除了可以自由地用目录组织文件以外,还可以直接用 m3u8 播放列表,而不用依赖 iTunes 里的弱智播放列表管理。至于像 iPhone 只能和一台电脑同步音乐这样莫名其妙的古老设定,在安卓上当然也是不存在的。

关于音乐,在水果这边还有个奇妙的设定:我不知道你知道不知道,iPhone 其实原生支持 FLAC 编码的音乐!如果你在 Files 或者 iCloud Drive 里放个 FLAC 文件,是可以直接播放的。但!是!iTunes 里不支持导入 FLAC 音乐,所以 iOS 自带的音乐播放器依然不能播放 FLAC 文件⋯⋯由于 iTune 支持的音乐格式太少,我的音乐库有个特别弱智的 hack。在我家里的服务器上,有个 music 目录,里面按照专辑存放着所有的音乐:

% ls -1 | sort -R | head -n 4
André Cluytens - 1958 [Shostakovich -- Piano Concertos; 3 Fantastic Dances; 5 Preludes & Fugues, Op. 87]/
Itzhak Perlman - 1977 [Goldmark Violin Concerto - Sarasate Zigeunerweisen]/
Metallica - 1991 [Metallica]/
Ginger Baker Trio - 1994 [Going Back Home]/

由于这些音乐的来源不同,文件是不同的格式,比如在 iTunes 上买的是 AAC,在 HDTracks 上买的是 FLAC,本科和高中就一直流传下来祖传音乐是 MP3。除此以外还有少量的 WavPack 等奇葩编码。但是如果我把这个 music 目录拖到 iTunes 里,是不能导入全部音乐的,因为 iTunes 只支持 AAC 和 MP3。这个问题最简单的解决方法当然是把不支持的文件全都转成 AAC,我可以在专辑目录里再开两个目录,叫 “flac” 和 “aac”,分别放两种编码的版本。这样如果我把 music 目录拖到 iTunes 里,就可以一键导入所有音乐了。

但是这个方法有个 bug,就是在其他音乐播放器上(比如 Foobar 2000),把 music 拖进去会出现重复的音乐⋯⋯我的解决办法是在 music 目录外面开一个 music_copy 目录,把转码的版本全都放到这个目录里,music 目录保留原始版本。这样如果一个专辑本来就是 AAC 或者 MP3,就只会存在 music 目录里;如果是 FLAC,就会在 music 里存放 FLAC 版,在 music_copy 里存放 AAC 版。如果我需要导入到 iTunes 里,就把这两个目录一起拖进去,而如果是其他的播放器,就只需要拖 music 目录。

没错,这一切都是因为我要迁就垃圾 iTunes。

安卓这边自然没有这个问题,像 FLAC, Vorbis 这些自由的编码都是支持的,甚至像 Opus 这样的最新最好的编码也没问题,不要问我为什么会有 Opus 编码的音乐⋯⋯

我常用的其它程序在安卓大多都有对应,

  • 比如 OTP Auth,这是一个个人开发的 OTP 软件,而且是自由的,基本上在 iOS 里是最好用的了,强烈推荐。在安卓里我换成了 Aegis,同样也是自由软件,重要的是这个 app 和 OTP Auth 一样,可以直接设置 OTP 的 hash 算法,位数等等。

  • Twitter 客户端用了 Twidere,没什么大毛病,有些行为和我惯用的 Twitterrific 不一样,但是习惯就好了。

  • 我同时用很多聊天软件,包括 iMessage。忽悠里面仅有的几个联系人换成了 Signal,但是不得不说,Signal bug 真的多⋯⋯干啥都有 bug⋯⋯

  • 天气软件是我没想到的,在安卓上我居然没找到能和 iOS 自带天气软件一样支持多个城市同时还不难看的,目前在用 OpenWeather。

  • 另一个没找到合适 app 的门类是计算器,不过倒是不怎么奇怪,毕竟 iOS 上的 PCalc 太优秀了,我的需求也比较奇葩(RPN + 好看 + 非模拟真・计算器)。目前正在自己写⋯⋯

对于我来说,水果这边最不可替代的其实是果表,目前在安卓平台还没有找到合适的对应。我把十多年前买的 G-Shock GW2500B 又挖了出来,依然运行良好。

组装键盘记

2020-07-23 21:05:00

自从忍痛流浪购买了全宇宙最贵的薄膜键盘以后,我就发现了一个一般人我不告诉他的秘密:樱桃的键盘开关手感真的挺烂的。但是这个键盘又不像樱桃一样能随便换键帽,如果我想要好的手感,同时还想换花里胡哨的键帽该怎么办呢?答案当然是自己 DIY 一个比全宇宙最贵的薄膜键盘还要贵的机械键盘,这就是键盘侠们经常挂在嘴边的定制键盘。

初期调研

一说到定制,键盘侠们的第一反应肯定是选择很多,琳琅满目。但是实际上在考虑到个人需求以后,往往选择就不那么多,甚至没有了。比如我需要有数字小键盘,这基本上已经把 90% 的选择刷掉了。因为市场上的定制键盘绝大部分都是所谓的「60%」构型,就是只有主键区的那六十几个键。剩下的那小部分里的大部分也都是 tenkeyless,和 70% 等等,都是没有数字小键盘的。想要小键盘,就只有两种构型:全尺寸和 96 键。全尺寸我觉得还是太宽了,如果在旁边放上鼠标的话,要么鼠标离得太远,要么主键区不在中央,都不好。所以最后就剩下 96 键一种构型了。这个构型一般人可能听都没有听说过,因为批量生产的成品键盘里据我所知就只有一个品牌的一个型号使用了这个构型,后面我会再次提到。一般的定制 96 键会使用下图这个键位。

96key default

可以看到这种键位保留了完整的数字小键盘,同时又有完整的方向键和 home, end 等按键,几乎覆盖了全尺寸键盘的所有键。但是明明这个键盘的按键比标准的 104 键要少啊,都少了那些键呢?答案是右边的 alt 和 super,加上 prtsc, scroll lock 和 pause。Alt super 什么的就不说了,scroll lock 和 pause,没什么用的,去掉也不可惜吧?

当然可惜了!像这样完全没有用的键,才是设定快捷键的最佳选择,因为几乎不可能冲突!在我的 Windows 游戏电脑上,这两个按键我绑定了 OBS 录像和广播功能。有人说了,绑定组合键不行么,比如 ctrl+f12 什么的?不行,尤其是在游戏电脑上。因为很多游戏里 ctrl alt shift 这些键都不是 modifier,而是独立起作用的(比如按 ctrl 切换下蹲/站立),绑定 ctrl+f12 会与这些功能冲突(不要问我是怎么知道的)。像 scroll lock 这种操作系统和应用程序肯定不会绑定任何功能的按键屈指可数,尤其宝贵。

除了缺少这些键以外,这个键位还有几个缺点,比如 home end 这些键不是按照标准键位排列,需要时间习惯;再比如右 shift 和小键盘的零都比全尺寸的要短。这些都不是什么大问题,但是如果能解决的话还是会方便很多。有没有不存在这些缺点,同时又使用 96 键构型的「完美键盘」呢?听起来似乎不太可能,但是确实是有。这就要说回我之前提到的唯一一种量产 96 键键盘:Cooler Master Masterkeys Pro M

cm masterkeys pro m
Figure 1. Cooler Master Masterkeys Pro M,键位是这个键盘的主要卖点之一。

当然这个键盘还是比之前的 96 键少了几个键,但我觉得精神是一样的。而且如果你仔细看数字键区,会发现这个键盘不仅有 home end 等键,还有 prtsc, scroll lock 和 pause,怎么做到的?答案在那个 num lock 上。Num lock 激活的时候,数字键区就是正常的数字键,但是在 num lock 关闭时整个数字键区就会变成导航区,这样就保留了标准键盘的所有按键。

⋯⋯

⋯⋯

咦?似乎有什么地方不对?标准键盘有 104 个键啊!而且也有 num lock 用来切换数字键区。这个 90+ 键的键盘不可能有标准键盘的所有键?!

你如果有这个想法的话,也没有错。这里矛盾的地方在于标准的 num lock(以及 caps lock)是一个特殊的键。在标准键盘中,num lock 用来切换数字键和方向键。这个行为其实不是键盘本身定义的,而是操作系统定义的。这也就是为什么你可以在操作系统里用软件切换 num lock。换句话说,不管 num lock 打开还是关闭,键盘硬件输出的键码都是一样的,操作系统会根据 num lock 的状态转换键码。转换后的数字键和主键区上方那一排数字的作用是一样的,但是在操作系统里,数字键区的数字键码其实是独立的一组,和主键区的数字键码不一样;方向键也同理。Cooler Master 的键盘少掉的就是这些方向键。然而缺少这些方向键并不可惜,尽管它们是有功能的,但是与导航区的方向键重复;而且正是由于有功能,所以不能绑快捷键,成了鸡肋。这里也可以看出,这个键盘的 num lock 只是上面印了这几个字,它的功能不可能是标准的 num lock 功能,因为数字键和方向键的对应并不由键盘决定,这个 num lock 其实是定制键盘里常用的切换键层功能。

明白了这些以后,我们也能设计出类似的键位用在 96 键的定制键盘上,以下是我设计的键位。

mw96 0

按下右上角的 TG1 键以后数字小键盘会变成这样:

MW96 TenKey

而那个 num lock 键是真正的 num lock,这样如果由于某种原因,操作系统关闭了 num lock,我可以再把它激活。除此以外,我这个布局还有个彩蛋:这个键盘有 F13 和 F14!是的,相比标准 104 键键盘,这个布局不仅没有少键,反而还多出了两个键。这两个键虽然现在很少见,但是在以前的老键盘的上还是会经常出现的,有些老键盘甚至有 24 个 F 键。直到现在操作系统也都支持这些键。

既然有了这个布局,准备工作就差不多了,剩下的就是选配件。对于外壳和电路,我选了当时唯一一种有现货的型号:XD96。幸运的是,虽然官网上没有明确说明,这个型号是支持 QMK 的,可以很容易地实现我设计的键位。键帽选择了 EnjoyPBT 的 GrayScale。开关的选择我纠结了很长时间,还买了几个试键器,最后锁定了 Zealios 65g。在选择开关的过程中我还发现了一件事,不知道是不是由于我小时候用过了很长时间的老式键盘(薄膜键盘流行之前的键盘),我对段落感的要求极高(或者应该说极怪)。在我试过的十几种开关里,就只有 Zealios 和凯华的 click bar 开关在我看来算是有段落感。像很多人交口称赞的 Outemu 天蓝和各种仿樱桃褐色,我按起来感觉就像有毛病的线性开关⋯⋯凯华的 click bar 我觉得手感比 Zealios 还要更好些,但是真的太吵了,不得已选择了后者。

组装

啊,XD96⋯⋯组装过程真是一言难尽。这个键盘的设计有个不大不小的坑,就是支撑开关的那个铝板左右两边没有螺丝,所以装好以后如果使劲按左右两边的键,整个支撑板和电路板结构会变形一小点。当然一般打字时是感觉不出来的,但是作为一个比全宇宙最贵的薄膜键盘还贵的定制键盘,各方面都要做到完美才对。这个问题有 Reddit 用户给出了解决方案,就是自己 3D 打印两个支撑的结构放在外壳和支撑板中间。我试了一下效果还可以。

除此以外,这个键盘还有个惊天神坑,见下图。

xd96 usb
Figure 2. ???????????

谁能告诉我这是怎么设计出来的?嗯?如果不是设计出来的,难道是加工时的公差?有人见过不到一厘米的开孔有几毫米的公差么?有么?这里我不想吐槽国产货怎么怎么样,只说一句:都是国产货,这水平还不如当年的白沟。

当然这个巨坑我最终还是填上了。我买了一套锉刀,把这个开口扩大了大概 3 毫米⋯⋯

扩大后的 USB 口
Figure 3. 扩大后的 USB 口

组装这个键盘的倒数第二步,是把玻璃背板装到外壳上,并用螺丝固定。那个螺丝也是我见过的最烂的没有之一。在拧的过程中十字坑就已经花了⋯⋯但是写到这里我也不想再说什么更多的了,就这水平,爱咋咋地吧。

最后一步是装键帽,也有坑!PBT 的键帽在加工过程中会变形,所以有时一些长键出厂时是弯曲的。我手里的这套 EPBT 键帽,所有 1.5u 或更长的键帽都是弯的,装上以后按下弹不起来。这个问题我以前早有耳闻,只是没想到会这么严重。解决办法也是有的,就是把键帽放到开水里加热一下,然后拿出来往反方向掰,直到冷却。不过不要以为 PBT 在开水里一煮就软了,可以随便掰;PBT 好歹是比 ABS 还硬的塑料,是有尊严的。我掰了一晚上,基本上把所有长键都纠正了,除了数字键区的加号。因为那是我最后掰的一个,手上实在没劲了⋯⋯所有键帽都装好以后,组装就算完成了。

刷固件

QMK 的固件刷起来特别方便,只要在 Configurator 里设置好键位,点一下 Compile,就可以直接下载编译好的固件了。不过我还加了一个小功能,就是把 num lock 写死成打开的状态。在 keymap.c 里我有这么几行:

void led_set_keymap(uint8_t usb_led)
{
    if(!(usb_led & (1<<USB_LED_NUM_LOCK)))
    {
        register_code(KC_NUMLOCK);
        unregister_code(KC_NUMLOCK);
    }
}

我的键位后来还修改了几次,最终版本在这里

总结及未来展望?

到这里这个键盘就算真正完成了,虽然过程比较坎坷,最终效果还是不错的。

xd96 final

但是生命在于折腾,俗话说得好,树折腾死,人折腾活。这个键盘我已经用了大概八个月,还记得我之前说那些长键都是我一个个掰过来的么?有些键已经开始偷偷地回弹了,虽然目前还不影响使用,但我觉得是时候考虑换键帽了。目前有两个候选,一是某种 MT3 的键帽,比如 MT3 /dev/tty。但是这种键帽有两个问题,

  1. 凹陷的形状是球形的,可能打游戏不方便,不确定。

  2. 目前只有 Drop 上有货。但是 Drop 的版本没有平的底排键,所以 ctrl alt 这些键用大拇指按的话会硌手,这个问题对于球形凹陷的键帽尤其严重。

另一个选择是等一波合适的 GMK,传说中 GMK 是质量最好的 ABS 键帽。一般来说 ABS 的键帽用不了几个月就会开始打油,但是好的 ABS 可以坚持更长时间。我在办公室用的 Type Heaven 就是 ABS 的键帽,我连续用了快四年,只在少数一些键上有非常轻微的打油。但是 GMK 每种一般就只产一次,所以只能等下一波合适的。

除此以外这个键盘也没什么其他好折腾的了。如果有机会的话,我的下一个定制键盘大概就会是支持热插拔的了,可能会试一下凯华的 click bar 开关,毕竟吵死人不偿命,吵死一个是一个。

Raspberry Pi 2 模拟 Switch 手柄

2020-04-25 11:47:00

最近看到了一个叫 joycontrol 的玩意,可以通过蓝牙模拟 Switch 手柄。原则上这个东西可以装在任何 Linux 机器上,README 里也说在 Ubuntu 和 Raspberry Pi 4 上测试过,但是我手上只有一个 Raspberry Pi 2B+,不自带蓝牙,我只好单独买了个 USB 蓝牙适配器。注意很多蓝牙适配器是不支持 Linux 的(比如我一开始看到的 TP-Link UB400),买的时候还是要看一下。

我的树莓派上装的是官方推荐的 Raspbian,在安装 joycontrol 的过程中踩了很多坑,最终基本都可以归结到一个问题,就是软件仓库里只有 Python 3.5,而 joycontrol 用到了一些 3.6 之后才有的特性,比如 f-string(难道我会告诉你我是昨天才知道 Python 有 f-string 的这个秘密么)。当然大便有很多 backport 仓库,但是我懒得折腾了,决定手动编译 Python 3.8。在编译之前,还需要安装这些包:

# apt install ffi-dev libdbus-1-dev libdbus-glib-1-dev libbluetooth-dev libhidapi-hidraw0 libhidapi-libusb0

其中 libbluetooth-dev 是 Python 支持蓝牙的头文件,没有这个 Python 就不能支持蓝牙的 socket;FFI 和 dbus 是后面编译 dbus-python 需要;libhid(好像)是运行 joycontrol 需要。

有了这些以后,剩下的就简单了。按照正常工序编译安装最新版 Python,并使用其中的 pip 安装 dbus-python。最后 clone joycontrol 的仓库,按照 README 里的方法安装测试就好。

整个安装过程总结成一句话就是:滚动升级大法好。