MoreRSS

site iconPhuker修改

信息安全研究者,Blue-Whale 成员,INTP
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

Phuker的 RSS 预览

一种基于小米中枢网关米家自动化极客版的室内恒温控制系统

2024-01-08 01:30:00

概述

洒家在开着空调睡觉时,老是会冻醒或者热醒,所以想在室内实现恒温。之前基于米家 APP 已经成功搞了一套恒温系统(具体方案以后再写),后来看到小米新出的小米中枢网关有一个米家自动化极客版的功能,可以基于图形化编程实现更丰富的自动化。洒家好奇图形化编程的表现力和效果如何,于是就买了一台玩了一下。这篇文章主要介绍洒家搞出来的这套实现室内恒温的方案,基于小米中枢网关的米家自动化极客版功能,编程读取米家智能温湿度计 3 的温度数据,负反馈控制空调、暖风机的开关与设置,从而自动化控制室内温度。同时讨论一下米家自动化极客版存在的产品设计问题。

按照洒家博客的惯例,本文不详细介绍基本操作、图形化编程概念等别人写过的最基础的东西。如果不熟悉这些基础知识,请先查阅小米官方和其他用户写的教程:

设备

可能由于功耗、续航、可移动性、减少发热对温度测量结果的影响等原因,目前小米所有的智能温湿度计,包括小米电子温湿度计小米米家电子温湿度计 Pro小米米家蓝牙温湿度计 2米家智能温湿度计 3,都是纽扣电池供电的,并且只支持通过蓝牙网关联网,不支持通过 Wi-Fi 联网。如果想要联网实现自动化,就需要一台能提供蓝牙网关的设备。本文介绍的方案中,小米中枢网关已经自带了蓝牙网关,因此米家空调伴侣 Pro 万能遥控版自带的蓝牙网关是重复的,可以替换为不带蓝牙网关的普通版空调伴侣智能插座。

如果空调是智能空调,可以直接接入米家,则不需要空调伴侣智能插座。如果空调是冷暖型的,则不需要额外购买制热的设备。洒家住的公寓只有一台单冷型空调,因此又额外购买了一台米家石墨烯暖风机用于制热。

程序和设置

米家自动化极客版部分

米家自动化极客版恒温控制自动化程序截图
米家自动化极客版恒温控制自动化程序(主程序部分)
米家自动化极客版恒温控制自动化程序截图
米家自动化极客版恒温控制自动化程序(子函数部分)

洒家的程序针对的是上文所述的单冷空调和暖风机两台设备,如果只有一台冷暖型的空调,对子函数部分稍加修改就可以正常工作。

编程和配置时需要注意:

  • 为避免出现竞争条件,开启/关闭设备和开启/关闭自动化的先后顺序应该是:
    • 开启时,先开启设备,再开启自动化。
    • 关闭时,先关闭自动化,再关闭设备。
  • 为防止设备频繁发出提示音,在开关和设置设备时,应该先检查该项目是否已经到达目标状态,如果已经到达目标状态就不做操作;或者直接禁用设备提示音。
  • 如果制热和制冷不是同一台设备,开启其中一台设备时,要关闭另一台设备。
  • 为防止频繁开启和关闭设备,目标温度需要设置成一个范围,温度上限和下限之间的间隔要合理设置,不能太小。
  • 目标温度范围是个性化的设置,对于不同的人和房间,合理的温度范围都有可能不同,需要多试一试,根据实际感受进行调整。

米家 APP 部分

创建 4 个手动控制,用于手动产生虚拟事件,从而控制自动化。

操作步骤:点击智能 - 右上角加号 - 手动控制,输入手动控制名称,点击添加执行动作 - 设备 - Xiaomi 中枢网关 - 产生虚拟事件,输入虚拟事件代码,点击右上角对勾确认,点击创建保存。点击刚刚创建的手动控制 - 更多设置,根据需要设置显示在房间页通过小爱语音控制以及添加到桌面快捷操作

4 个手动控制的名称和虚拟事件代码如下:

  • 开启自动制热event_enable_auto_heating
  • 开启自动制冷event_enable_auto_cooling
  • 关闭自动控温event_disable_auto_temperature
  • 查询自动控温状态event_query_auto_temperature_status
米家 APP 创建手动控制截图
米家 APP 创建手动控制

创建 4 个自动化,在点击查询自动控温状态后,响应小米中枢网关产生的虚拟事件,产生通知和日志,从而接收查询结果。

操作步骤:点击智能 - 右上角加号 - 自动化,开始创建自动化。点击添加触发条件 - 设备 - Xiaomi 中枢网关 - 虚拟事件发生,输入虚拟事件代码,点击右上角对勾确认;点击添加执行动作 - 通知,输入通知内容。点击创建,保存时输入自动化的名称。

4 个自动化的虚拟事件代码,通知内容和名称如下:

  • status_auto_cooling_enabled自动制冷已开启查询自动制冷状态为开启
  • status_auto_cooling_disabled自动制冷已关闭查询自动制冷状态为关闭
  • status_auto_heating_enabled自动制热已开启查询自动制热状态为开启
  • status_auto_heating_disabled自动制热已关闭查询自动制热状态为关闭
米家 APP 创建自动化截图
米家 APP 创建自动化

设置完毕后,米家 APP 的首页和智能页看起来是这样的:

米家 APP 首页截图
米家 APP 首页
米家 APP 智能页截图
米家 APP 智能页

操作方法和效果

平时只需要在手机上操作,不需要在电脑上打开米家自动化极客版的网页。在米家 APP 的首页房间页点击之前创建的 4 个手动控制,在夏天点击开启自动制冷,冬天点击开启自动制热,需要关闭时点击关闭自动控温即可。喜欢语音控制的读者也可以通过小爱语音控制。

开启自动控温后,可以成功实现室内恒温,温湿度计的温度统计曲线基本上是一条横线。洒家实验了几个晚上,配置好参数后,实际体验效果不错,开着空调睡觉时再也不会冻醒或者热醒了。

米家 APP 米家自动化极客版恒温控制效果截图
米家自动化极客版恒温控制效果

一些实践经验:

  • 最好不要让空调直接对着人和温湿度计吹。
  • 温湿度计要放到人的旁边,例如如果想要在床上睡觉时恒温,就要把温湿度计放到床边。
  • 温湿度计旁边不能有热源,例如手机充电器。

点击查询自动控温状态时,可以在手机通知或者米家 APP 右上角的日志中看到查询结果:

米家 APP 日志截图
米家 APP 日志查看自动控温开启状态

米家自动化极客版的产品设计问题

目前1米家自动化极客版这一套图形化编程方案有很多问题,不知道小米是出于什么原因选择了这一套方案。洒家认为,小米首先应该搞一个易用的社区自动化程序分享平台;其次应该把图形化编程改成表现力更强的代码编程,并提供在代码中声明参数、设备等配置项的 API,自动生成配套的图形化设置界面。具体分析如下:

编程本身就是有门槛,且令普通人望而却步的事。虽然图形化编程看起来简单一点,但是也是有学习成本的,个人估算图形化编程并不能显著增加用户量。假设总用户量为 10000 人,可能只有 100 人会用图形编程,10 人会用代码编程,100 人相对总数 10000 人仍然是一个很小的比例。洒家认为,与其用图形化编程降低编程门槛,不如搞一个类似 Greasy ForkSteam 创意工坊的社区程序分享平台。再简单的编程也比不上不用编程,如果“小白”用户可以在社区里搜索自己的使用场景,一键下载“大神”(包括小米员工)发布的自动化程序,简单改几个参数,自动化就能运行起来了,这样才足够简单,才能把用户量搞上去。

在“大神”带动“小白”的局面下,为了让“大神”(包括小米员工)编程编得舒服,应该把图形化编程改成表现力更强的代码编程。对比代码编程,图形化编程有很多问题:

  • 目前的图形化编程的表现力和代码差距太大,也就比米家 APP 的功能强大一点,但是高不成低不就,也许就适合懂一点编程思维,但是不会写代码的人。主要表现如下:
    • 很多简单的功能,例如数值运算、一些逻辑比较和判断,在正规的编程语言里就是一些简单的运算符的组合,但是在米家自动化极客版里,官方没有提供卡片,就无法实现。
    • 没有变量/常量的概念。一些配置参数(自动开启和关闭时间、目标温度)散落在各处不容易集中管理,程序复杂起来就会出现重复,修改时也容易遗漏。这个问题就和 CSS 变量想要解决的问题类似。
    • 没有函数、子程序,重复的组合操作不太方便抽象出来,程序容易变得复杂和冗余。目前似乎只能用虚拟事件模拟没有参数和返回值的函数调用。
  • 图形化的程序无法复制,不易分享和交流。这篇文章本身就是一个例子,竟然在用截图分享程序。而代码天然支持复制和粘贴。即使没有官方社区程序分享平台,尽可能支持开放自由地交流也可以促进整个社区的繁荣。
  • 不方便查看日志,日志也是在原图形化界面上逐步显示的,复杂一点的程序调试起来很困难,眼睛都快看瞎了。
  • 卡片信息密度太低,即使右键点击“简化卡片”后,复杂一点的程序一个屏幕都显示不完。另外,为了整洁美观,方便查看,洒家把很多时间浪费在调整卡片的对齐和布局上了。
  • 从厂商的角度,这种复杂的功能在实现上也容易出现 bug,且不容易测试,人力成本太高。洒家发现很多 bug 都是很容易复现的,但是不知道是没有测试出来还是没有来得及修复就上线了。再加上这个功能本身比较小众,用的人太少,投入的人力就不会太多,解决 bug 的速度也会很慢,这就会造成恶性循环。如果改成代码编程,能大幅降低开发难度,降低成本;用户量上去之后还能争取更多资源投入,形成良性循环。洒家目前遇到的具体 bug 包括但不限于:
    • 有时候会有自动化失效的问题,需要在网页上把出问题的自动化关掉再打开,或者拔插小米中枢网关的电源解决。
    • 目前事件发生或状态更新卡片获取米家智能温湿度计 3 的温度有 Bug,经常产生不了事件,导致自动化失效。似乎可以用循环加上查询当前状态替代。
    • 日志显示,一些浮点数有精度问题,例如获取米家智能温湿度计 3 的温度可能得到 25.200001 的结果,洒家没有仔细研究,猜测可能会导致一些逻辑判断的 bug。
    • 使用查询当前状态查询米家空调伴侣 Pro 万能遥控版空调 - 设定温度,条件设置为介于,会出现满足条件否则 2 个分支同时执行的情况。

总之,只有用开放的思维,帮助社区用户充分发挥无穷的创造力,让用户之间充分交流,形成“大神”带动“小白”的局面,才更有希望把用户生态搞活,提高商业价值,实现用户和厂商的双赢。如果小米或者其他公司看到了这篇文章获得了启发,真的把洒家的设想实现了,简单致谢一下就行了。

Footnotes
  1. 目前:2024 年 1 月,小米中枢网关的固件版本为 3.1.0_0051,米家自动化极客版的版本为 v1.4.0

随手拍·2023

2023-12-31 17:30:00

徒步,从小梅沙到大梅沙

沿着海滨栈道徒步前行,从小梅沙到大梅沙,2023 年从这里开始。

小梅沙海滨栈道 | 广东 深圳
小梅沙海滨栈道 | 广东 深圳
大梅沙海滨公园 沙雕创作 | 广东 深圳
大梅沙海滨公园 沙雕创作 | 广东 深圳
大梅沙海滨栈道 | 广东 深圳
大梅沙海滨栈道 | 广东 深圳
从海滨绿道望向盐田国际集装箱码头 | 广东 深圳
从海滨绿道望向盐田国际集装箱码头 | 广东 深圳

最后一路走到码头门口,但是这里似乎不让随意参观。

从大沙河到深圳湾

清华大学深圳国际研究生院 | 广东 深圳 大沙河
清华大学深圳国际研究生院 | 广东 深圳 大沙河
深南大道沙河大桥 | 广东 深圳 大沙河
深南大道沙河大桥 | 广东 深圳 大沙河
赛艇 | 广东 深圳 大沙河
赛艇 | 广东 深圳 大沙河
华润城·润玺一期/二期花园 | 广东 深圳 大沙河
华润城·润玺一期/二期花园 | 广东 深圳 大沙河
落日 | 广东 深圳 深圳湾
落日 | 广东 深圳 深圳湾
深圳人才公园 | 广东 深圳
深圳人才公园 | 广东 深圳
海鸟 | 广东 深圳 红树林海滨生态公园
海鸟 | 广东 深圳 红树林海滨生态公园

深圳的绿道

深圳的绿化做得不错,有许多绿地、公园、绿道零星遍布整个城市。洒家很宅,不常运动,但是每次出门徒步、爬山、骑行,呼吸时嗅着一阵阵自然的气味,都能感到压力和焦虑在慢慢离去。

问山叠水 | 广东 深圳 环西丽湖碧道
问山叠水 | 广东 深圳 环西丽湖碧道
不知是谁手工制作的交通指示牌 | 广东 深圳 梅林绿道
不知是谁手工制作的交通指示牌 | 广东 深圳 梅林绿道

前海湾

落日 | 广东 深圳 前海演艺公园
落日 | 广东 深圳 前海演艺公园

仙湖植物园

沧海桑田的硅化木(植物化石)| 广东 深圳 仙湖植物园 化石森林园
沧海桑田的硅化木(植物化石)| 广东 深圳 仙湖植物园 化石森林园

这些硅化木形成于几千万年甚至上亿年前,历经沧海桑田,又被人类重新立起来,做成了化石森林景观。洒家摸着这些冰冷的石头,不禁感叹人类之渺小,人生之短暂。

大芬油画村

静物写生 | 乔治·莫兰迪 | 1960 | 广东 深圳 大芬油画村
静物写生 | 乔治·莫兰迪 | 1960 | 广东 深圳 大芬油画村
白色小路(景观)| 乔治·莫兰迪 | 1941 | 广东 深圳 大芬油画村
白色小路(景观)| 乔治·莫兰迪 | 1941 | 广东 深圳 大芬油画村
景观 | 乔治·莫兰迪 | 1942 | 广东 深圳 大芬油画村
景观 | 乔治·莫兰迪 | 1942 | 广东 深圳 大芬油画村

详情请看之前这篇:大芬油画村半日游

珠江

珠江与晚霞 | 广东 广州
珠江与晚霞 | 广东 广州

南京

在清冷的小雨中漫步宽阔的古城墙 | 江苏 南京
在清冷的小雨中漫步宽阔的古城墙 | 江苏 南京

郴州

丹霞地貌 | 湖南 郴州 高椅岭
丹霞地貌 | 湖南 郴州 高椅岭
丹霞地貌 | 湖南 郴州 高椅岭
丹霞地貌 | 湖南 郴州 高椅岭
雾漫小东江 | 湖南 郴州 东江湖
雾漫小东江 | 湖南 郴州 东江湖

江面上的雾是湿空气遇到温度较低的江水形成的。东江湖上还有专门在渔船上表演撒网的人。

雾中的仰天湖 | 湖南 郴州 仰天湖大草原
雾中的仰天湖 | 湖南 郴州 仰天湖大草原

这里让我想到了莫奈的《睡莲》系列作品。

雾中的仰天湖 | 湖南 郴州 仰天湖大草原
雾中的仰天湖 | 湖南 郴州 仰天湖大草原

去之前没仔细做攻略,到了才知道,原来仰天湖大草原在山上。山路十八弯,车很难开,开车的兄弟的驾驶水平很了不起。当天下着小雨,山上全是雾,没有多少人,跟网上查到的平常的景像完全不一样,有一种沉静的世外之美。

郴州不仅自然风光很美,回来之后才知道,当年造原子弹用的铀原料也来自这里的 711 矿

下川岛

海上的彩虹(用肉眼看更鲜艳)| 广东 江门 下川岛
海上的彩虹(用肉眼看更鲜艳)| 广东 江门 下川岛

听说在岛的东边可以看到日出。一大早趁天还没亮时起床,想去租一辆电动车,还怕岛上租车的小店都没有开门,结果一出酒店,租车的老板已经把车停在门口等着做生意了。一路飞驰,早晨的凉风飕飕,到达米岩观日出景点时,岸边的礁石上已经挤满了人。望着东边的海平线,慢慢等到了日出的时间,天上却全是云,把太阳层层遮住了。这时,我们在西边意外地见到了彩虹。

巽寮湾

游艇出海 | 广东 惠州 巽寮湾
游艇出海 | 广东 惠州 巽寮湾

坐着大巴车沿着海岸线前进,在路边见到了一些烂尾楼。印象最深的是,有一家自己用塑料布封住了窗户,还装了空调,不知道水电是怎么解决的。

演出

剧院魅影中文版 | 广东 广州 广州大剧院
剧院魅影中文版 | 广东 广州 广州大剧院

个人感觉这部由韦伯作曲的经典音乐剧整体很好听。开场吊灯升起,Overture(序曲)奏响全场时非常震憾。很多曲子很优美,例如上半场的 Think of Me(想念我)(这首歌也出现在了武林外传第三十回中);有的曲子的旋律又似曾相识,好像在哪听过。推荐叨叨冯聊音乐对这部音乐剧的讲解,看完表演再看讲解又有了更深的理解。

演出后发现这部音乐剧还有个续集 Love Never Dies(真爱永恒 / 爱无止尽),洒家看了一下剧情简介,感觉非常扯淡。

风居住的街道 - 日本当代治愈系钢琴家矶村由纪子音乐会 | 广东 深圳 南山文体中心
风居住的街道 - 日本当代治愈系钢琴家矶村由纪子音乐会 | 广东 深圳 南山文体中心

洒家 10 多年前在一位喜欢日本文化的同学那里第一次听到了矶村由纪子的音乐,没想到这次还能来听现场的演奏会。表演者共 3 个人:矶村由纪子(钢琴),甘建民(二胡),丸田美纪(日本筝)。甘建民是旅日多年的华人二胡演奏家,除了演奏,还负责翻译和报幕。感觉他在介绍时,不太熟悉曲子和搭档的中文名;另外他也有点忙不过来了,有一首曲子演奏完,不小心顺口说起了日语。

这次演出的曲子很好听。除了最经典的《风居住的街道》,洒家最喜欢的是《樱花盛开》。可惜这次没有演《绯红华尔兹》。由于现场三人用的乐器是固定的,因此有些曲子和录音版本不同。

表演结束后,主办方又搞了个交流会环节,观众可以向表演者们提问。现场有几位资深粉丝用流利的日语提问,甘建民表示,自己已经去日本几十年了,还没有他们的日语流利。矶村由纪子现场透露《风居住的街道》的创作背景:多年前她第一次来中国的时候,在广州看到了一条河,曲子的旋律就自然出现在她的脑海中了。个人猜测这条河有可能是珠江。

摇滚莫扎特中文版 | 广东 深圳 保利剧院
摇滚莫扎特中文版 | 广东 深圳 保利剧院

演出前洒家只是简单看了一下莫扎特的生平和剧中人物关系,歌曲则是在现场第一次听。听完之后感觉有些歌没有什么记忆点,但是回去之后仔细研究了几天,又感觉越听越好听。以后看演出之前一定要充分预习几遍,把曲子听熟,否则就浪费了。

个人最喜欢的 3 首歌是:

资源推荐:

“美丽星期天”:光影之鸣——管风琴赏析音乐会 | 广东 深圳 深圳音乐厅
“美丽星期天”:光影之鸣——管风琴赏析音乐会 | 广东 深圳 深圳音乐厅

这场演出的定位是公益、入门熏陶,大部分都是影视通俗曲目,并不深奥,对观众的门槛很低,甚至连票价也是免费的。演出的形式也不严肃,在曲目之间,表演者母子两人用简短的“尬剧”衔接,非常滑稽,在表演前有时还会有对曲子和乐器的讲解和科普。可惜,可能因为这是免费的演出,很多人并不珍惜,迟到了好一会才进来。

曲目单里本来有一首 Charles-Marie WidorC.M. 维多尔:管风琴第五交响曲,Op.42,No.1,第一乐章,去之前专门预习了好几遍,现场却没有表演。《摇摆巴赫》这首曲子在演出前搜不到具体指的是什么,实际是巴赫著名的 Toccata and Fugue in D minor, BWV 565 的改编,果然一提到管风琴,这首曲子永远都逃不掉。除了器乐演奏之外,赵小玲还在管风琴的伴奏下用英文唱了一首《我心永恒》,最后还邀请观众一起合唱了《我和我的祖国》,可惜演奏大厅的大门一关,手机一点信号都没有,记不清歌词也没办法现场搜。

洒家上大学时,执行力比现在还差,最大的遗憾之一就是没有去当地的大教堂听一场管风琴演奏。这次听完之后洒家感觉管风琴的声音确实非常震憾,听的时候起了一身鸡皮疙瘩。可以想象,古代没有大音箱,人们在教堂里听到这样震憾的音乐,一定想当场跪拜在神的面前。

民乐映九州|“秦淮烟雨行”江南丝竹音乐会 | 广东 深圳 南山文体中心
民乐映九州|“秦淮烟雨行”江南丝竹音乐会 | 广东 深圳 南山文体中心

个人感觉演出曲目中最好的一首是《过雨荷花》,现场出演的人和视频里一样,也是方嘉莹(琵琶)和雷焕然(古筝,作曲)。视频下面有一条评论写得不错,摘录过来:

现场听更好听支持。两个乐器的声音好像在交谈,又好像是雨声,时而是淅沥的雨滴,时而是狂风骤雨。曲子很有新意,没有局限于传统的五声音阶,E4 G4 A4 B4 D5 E5 C5# A4 B4 那个乐句反复出现也很有记忆点。

还有一首《春江花月夜》印象也比较深,在每一段结尾,萧在演奏时做了渐慢处理,和之前找的录音版本的诠释不一样。但是这次演出大部分曲子的音阶和节奏型的套路都很相似,风格也都差不多,旋律比较缺乏记忆点,也许作为背景音乐还行,连着仔细欣赏的话,有些审美疲劳。去之前已经提前熟悉了几遍,但是有些曲子是新作品,录音、视频和谱子在网上都找不到。听完之后感觉听现场要比听录音好很多,声音更清晰和立体,还可以看到表演者的神态和动作,这也是音乐表演的一部分。

后记

很多研究网络安全与隐私保护的人都有个毛病,有时候会把自己的系统配置得过于安全,以至于有时候会影响自己正常使用。洒家就遇到了这种情况。洒家之前修改了手机的相机设置,不在拍摄的照片文件里嵌入精确位置信息。但是 20 岁之后,洒家感觉自己的记忆力开始慢慢减退,有一次翻相册里以前的照片,竟然想不起来是在哪里拍的。看来李彦宏的“用隐私换取便利”在一定程度上也是成立的。为了在未来更方便考证相册里的照片是在哪里拍的,洒家把在照片中嵌入位置信息的功能又打开了。拍照是一种记录生活中美好记忆的好方法,只需用手机随便拍几张,不用担心拍得不好看,也不用担心浪费胶卷,就可以记住在某一天去了哪里。至于隐私,只需要在分享照片文件的时候,记得根据需要清除 Exif 信息就行了。

替换硬盘底座的原装电源

2023-04-03 23:20:00

洒家有几个硬盘盒/硬盘底座/硬盘扩展坞。最近看了一些科普视频1,然后实际查看原装电源的铭牌,查阅硬盘详细参数表,发现这些硬盘底座产品的原装电源确实无法满足硬盘的供电需要。且不提纹波与噪声指标是否合格,就连最基础的输出电流都无法满足硬盘峰值需求,长期使用必然有损坏硬盘的风险,现实中也已经有大量硬盘损坏的案例。于是洒家决定把原装电源替换成明纬的更大功率的电源来降低损坏的风险2。洒家最终选择的电源的价格已经接近甚至超过了硬盘底座本身的价格,但是洒家认为这笔钱应该花,因为百十块钱的电源可以保护价值几百甚至一两千的硬盘,况且硬盘有价,数据无价。洒家这么多年被便宜货坑过不少,如果硬盘突然损坏,购买新硬盘的金钱成本、恢复备份和重建 RAID 的时间成本、数据丢失的损失都超过了电源的价格。

Shut up and take my money meme
Shut up and take my money!

在购买过程中,洒家被明纬电源的型号搞得眼花缭乱3,也没搜到原装电源插头的具体尺寸,自己量又量错了,一同买了 P1J4 转 P1M5 转接头,最后却没用上。因此,这篇博客不是给电源打广告,也无意煽动电源焦虑,主要是把洒家的经验和网上找不到的资料发出来,供读者参考。

硬盘底座概况

UGREEN 绿联 CM198 USB 3.0 硬盘扩展坞

UGREEN 绿联 CM198 产品宣传图片
绿联 CM198 宣传图片
UGREEN 绿联 CM198 产品说明书
绿联 CM198 说明书

产品概况:

  • 型号:CM198
  • USB 接口:USB 3.06
  • 硬盘接口:支持 2.5/3.5 英寸 SATA 硬盘,立式双盘位(产品宣传页和说明书没提支持不支持顺序上电,洒家拿了 2 块硬盘实际测试,听声音应该是同时启动的)
  • 其他功能:脱机拷贝,硬盘自动休眠(可修改休眠等待时间或关闭休眠功能)
  • 购买链接:京东自营

根据铭牌和实际测量及测试,硬盘扩展坞原装电源适配器概况如下:

  • 型号:CW1203000
  • 输入:100-240V 50/60Hz AC 1.2A Max
  • 输出:12V 3A DC
  • 制造商:深圳市成威源科技有限公司
  • 监制商:深圳市绿联科技有限公司
  • 插头:直头,内正外负,长度 10mm,外径 5.5mm,内径 2.1mm(实测适配明纬 P1J 插头)

ORICO 奥睿科 6518US3 单盘位 2.5/3.5 寸硬盘底座

ORICO 奥睿科 6518US3 产品宣传图片
奥睿科 6518US3 宣传图片
ORICO 奥睿科 6518US3 产品说明书
奥睿科 6518US3 说明书

产品概况:

  • 型号:6518US3
  • USB 接口:USB 3.06
  • 硬盘接口:支持 2.5/3.5 英寸 SATA 硬盘,卧式单盘位
  • 购买链接:京东自营

根据铭牌和实际测量及测试,硬盘底座原装电源适配器概况如下:

  • 型号:GQ24-120200-AC
  • 输入:100-240V 50/60Hz AC 1.0A Max
  • 输出:12.0V 2.0A 24.0W DC
  • 制造商:东莞市港奇电子有限公司
  • 插头:直头,内正外负,长度 12mm,外径 5.5mm,内径 2.1mm(实测适配明纬 P1J 插头)

选择电源型号

根据物理知识,我们平常接触的电源适配器一般都属于恒压源。电源的输出电压要和原装电源保持一致,硬盘底座这类产品一般是 12V。而电源的输出电流则不能低于用电器的峰值输入电流,需要综合考虑硬盘的峰值电流/峰值功率、设备是否支持顺序上电等因素,然后再加上一些余量。硬盘的峰值电流/峰值功率可以通过查阅厂商提供的参数表确定,可以把硬盘型号和 manualspecificationdata sheet 等关键词一起搜索,一般都可以搜到 PDF 格式的详细参数表。对于单盘位产品,12V 2A 可能不能满足一些硬盘的供电需要,至少需要 12V 3A 输出的电源。

洒家买的是明纬电源,下面是几种类似的型号:

型号 接地 电压 电流 纹波与噪声(mVp-p)
规格书 / 测试报告
链接
GSM60A12-P1J 12V 5A 100 / 72 京东自营 规格书 测试报告
GST60A12-P1J 12V 5A 120 / 59.6 京东自营 规格书 测试报告
GSM60B12-P1J 12V 5A 100 / 55.6 京东自营 规格书 测试报告
GSM40A12-P1J 12V 3.34A 100 / 52.5 京东自营 规格书 测试报告
GST40A12-P1J 12V 3.34A 120 / 50.8 京东自营 规格书 测试报告
GSM40B12-P1J 12V 3.34A 100 / 58 京东自营 规格书 测试报告
GSM36B12-P1J 12V 3A 120 / 80 京东自营 规格书 测试报告
GST36B12-P1J 12V 3A 100 / 22.8 京东自营 规格书 测试报告

其中 GSM 系列属于医疗用途7,贵一些;GST 系列则属于工业用途,便宜一些。对比产品规格书和价格,洒家原本以为两个系列的质量应该是 formula 的关系。后来看了官方提供的数年前的测试报告,发现 GSM 系列在纹波与噪声指标上并不一定就比 GST 系列强。可惜洒家既不会分析电源里面的电路结构和元件,又没有检测能力,只能纸上谈兵地猜测一下,大概 GSM 系列比 GST 系列价格贵在了满足医疗安全等标准方面。给硬盘底座供电,GST 系列应该就够用了。

明纬电源不带输入线,需要单独购买。输出插头都是 P1J4 规格的,如果需要其他规格的插头要另外购买转接头。洒家上面提到的 2 款硬盘底座的电源接口都是 P1J 规格的,不用买转接头,供读者参考。

Footnotes
  1. 听君一席话,消费两百多。

  2. 注意:替换原装电源并不能代替数据备份。

  3. 更乱的是,目前一共有 3 个明纬京东自营店铺,不知道互相是什么关系:明纬(MEANWELL)京东自营专区明纬(MEANWELL)电源京东自营专区明纬(MEANWELL)京东自营专卖店

  4. P1J:外径 5.5mm,内径 2.1mm,长 11 mm

  5. P1M:外径 5.5mm,内径 2.5mm,长 11 mm

  6. USB 3.0:即 USB 3.1 Gen 1 或 USB 3.2 Gen 1×1(USB 标准化组织 USB-IF 改名部的“杰作”),带宽 5 Gbps

  7. 然而无论是 GSM 还是 GST 系列,商品评价里大部分都是用于硬盘盒、硬盘柜,还有一些人用来烧 Hi-Fi。

大芬油画村半日游

2023-03-19 02:15:00

最近我们去大芬油画村逛了半天。

乔治·莫兰迪作品展览

我们这次主要想参观“世界艺术大师乔治·莫兰迪华南首展”,这次展览有乔治·莫兰迪的几十件作品真迹。洒家在绘画领域是个外行,只是以前在高中上过美术课,看过一些科普,认识几张名画。来之前洒家并不了解乔治·莫兰迪,通过看这次展览才逐渐了解了他的生平和作品。

导览手册折页正面
导览手册正面
导览手册折页背面
导览手册背面

下地铁进入大芬油画村,抬头就能看见路灯杆的广告牌上都是这次展览的广告。穿过一条街,街边都是和油画有关的店。走到尽头,我们看到了大芬美术馆,然后上二楼买票进入展厅。展厅入口堵着很多精心打扮的姑娘,她们也不进去看作品展览,只是一直在摆姿势,不停地自拍、她拍。万万没想到这里也沦为网红打卡拍照的地方了。

展厅入口
展厅入口

挤进展厅,里面人还是很多。乔治·莫兰迪的作品都挂在墙上,和人们隔着一条警戒绳。有的作品前围满了人,只能先看别的,等他们走了再挤过去看。洒家对着画拍了几张照片,回来再看,总感觉和现场看到的不一样。照片不仅颜色不准确,还看不到画的笔触、厚度、反光和质感。静物和风景都显得平平无奇,再也让人体验不到现场看的那种震撼,好像画里面的“灵魂”没了。

静物写生 | 1960
静物写生 | 1960
白色小路(景观)| 1941
白色小路(景观)| 1941
景观 | 1942
景观 | 1942
乔治·莫兰迪工作室布景
乔治·莫兰迪工作室布景

作为一个外行,洒家也说不上什么门道,只觉得他的画有一种吸引力,能吸引我盯着它们细细观察。看似简单的瓶瓶罐罐、花朵、郊外风景,好像是精心伪装的模样,实际上并不简单,不知道为什么能从里面感受到一种沉稳、宁静和永恒。

也许洒家在写文章时和乔治·莫兰迪有一些共通的追求。几年前有一篇高考满分作文《生活在树上》,洒家读了以后感觉很惭愧,就像高中时辞藻华丽的范文,自己这辈子学不了,也学不像。洒家写文章常常反复修改,只求用尽可能通俗凝炼的文字把思想精确地传递给读者,能做到“波泽春涨”,“润物无声”,偶有妙笔就可以了。

电视剧《雍正王朝》(1999)第 32 集截图
李卫:“你写的都是他妈的屁话!”

写意油画展览

出来后,我们又下到一楼参观了“发生·发现——深圳·中国写意油画巡礼”展览。这个展览大部分都是写意抽象朦胧的当代作品,放眼望去,色彩饱和度普遍比乔治·莫兰迪的作品高,风格有明显不同。下面是几张有点意思的作品:

时光的足迹 | 栗壮志 | 2021
时光的足迹 | 栗壮志 | 2021
《旅行遇见》之“暮归” | 卢卫文 | 2019
《旅行遇见》之“暮归” | 卢卫文 | 2019

逛大芬油画村

从美术馆出来,太阳还没落山,我们又在村子里逛了一会。

毛泽东画像(临摹)| 安迪·沃霍尔 | 1972 ~ 1973 | 波普艺术
毛泽东画像(临摹)| 安迪·沃霍尔 | 1972 ~ 1973 | 波普艺术

洒家之前看过一些岳敏君作品,“笑脸人”表现出来的“玩世现实主义”引起了我的共鸣。这次在一家店发现了他的临摹作品,对此很惊喜,这也是意料之外情理之中。

西游记(临摹)| 岳敏君 | 2011
西游记(临摹)| 岳敏君 | 2011

整个大芬油画村围绕着油画形成了产业。道路和胡同两旁主要都是自产自销的油画商店和工作室,也有画框装裱店,绘画材料店,还有指导零基础游客临摹照片体验画油画的店。这里有各种主题的油画,名画临摹比较多,梵高莫奈的名画几乎家家都有。还有风景画(甚至有 iPhone 自带壁纸)、吉祥寓意的装饰画、领袖标准画像、当代名人画像等。除了油画,洒家还见到了国画、刺绣和书法作品。很多老板正坐在挂满油画的店里临摹名画或者摄影作品,有的把照片贴在旁边,有的在旁边放着显示器,临摹也不用去野外或者展览馆了。有的老板还在旁边架着手机直播。有些店门口贴着画家的履历,我们正看着介绍,画家就看着我们疑惑地从门里走了出来,搞不好我们遇到了业内的名人。这些油画的价格并不贵,小幅的百十块钱就能买到,大点的也不过几百块钱。洒家看了之后很疑惑,不知道他们的产量和销量如何,毕竟人都是要恰饭的,他们靠画画能不能养活自己?另外,洒家在这里很少见到原创作品,对于追求艺术还是商业,原创突破还是批量生产,做大师还是工匠,他们有没有选择的机会?他们怎样面对理想和现实的矛盾?

回来之后洒家才知道,原来这里是全国乃至全球最重要的商品油画(行画)生产和交易基地。凭借低成本优势,在巅峰时期这里的近万名画工每年可以批量复制几百万张商品画。大部分产业工人是野路子出身,他们不能被称为画家或者画师,只能叫做画工,经过简短的培训之后就可以进入流水线干活。每个流水线上的画工甚至只需要负责一幅名画的一个局部,通过这种方式,大芬油画村甚至创造过 400 多名画工用一个半月生产 36 万张画的奇迹。因此,有人把这里略带批评地称作“艺术界的华强北”。

我们又看了纪录片《中国梵高》。片中的赵小勇临摹梵高的名画 20 多年,做梦都想见到梵高。终于,他到达欧洲,见到了梵高的真迹,却感受到了震撼、失落和迷茫。洒家对赵小勇的经历感同身受,感慨对艺术的追求确实是一种奢侈品。但是一旦萌生了创作原创作品的想法,改变了自己的定位,底层的画工也就从此走上了追求艺术的漫漫长路。

扩展阅读:

几种静态网站托管平台的 Web 服务访问特性实验对比

2022-11-25 00:10:00

最近洒家的 GitHub Pro 教育优惠到期了。洒家担心无法再从私有仓库发布 GitHub Pages 网站,于是提前研究了其他几款主流的静态网站托管平台,发现它们的 Web 服务配置和 GitHub Pages 有一些差别,服务器的行为特性各不相同。于是洒家设计了一套测试样例进行了更深入的实验,简单分析了一下实验结果,供读者在选择托管平台、配置静态网站生成器时参考。

概述

  • 测试时间:2022 年 11 月
  • 测试对象:
  • 用于测试的静态网站的目录结构:
/
|-- 404.html
|-- index.html
|-- test1
|   `-- index.html
|-- test1.html
|-- test2.html
|-- test3
|   `-- test3.html
`-- test4
    `-- index.html
  • 测试方法:部署上述静态网站后,使用各种路径访问,记录服务器的行为,并在不同平台间进行对比
  • 测试样例:
    • 基本测试:一组可以在 file:// 协议、Apache 服务器等最基本的场景正常使用的访问方式
    • 完整测试:所有可能的访问方式

测试结果

测试结果中,200 /index.html 表示 HTTP 状态码为 200,返回了 /index.html 的文件内容;301 --> /test1/ 表示 HTTP 重定向到 /test1/404 (default) 表示状态码为 404,返回了服务器默认错误页面,以此类推。

下列测试结果中,每个表格都会挑选一个测试对象作为标准测试对象,其他测试对象和标准测试对象对比,行为完全相同的测试点用绿色标记,行为不同但基本上可以等价替换的测试点用黄色标记(包括不同的 3xx 状态码跳转到了相同的 URL、都是 404 状态码但是响应消息正文不同等情况),行为完全不同的测试点用红色标记。红色的格子越多,和标准行为的差别越大。标准测试对象本身不做任何彩色标记。

基本测试

下表为基本测试的测试结果,以 Apache 为标准测试对象:

Apache GitHub Pages GitLab Pages Cloudflare Pages Vercel Netlify
/ 200 /index.html 200 /index.html 200 /index.html 200 /index.html 200 /index.html 200 /index.html
/index.html 200 /index.html 200 /index.html 200 /index.html 308 --> / 200 /index.html 200 /index.html
/test1.html 200 /test1.html 200 /test1.html 200 /test1.html 308 --> /test1 200 /test1.html 200 /test1.html
/test1/ 200 /test1/index.html 200 /test1/index.html 200 /test1/index.html 200 /test1/index.html 200 /test1/index.html 301 --> /test1
/test1/index.html 200 /test1/index.html 200 /test1/index.html 200 /test1/index.html 308 --> /test1/ 200 /test1/index.html 200 /test1/index.html
/test2.html 200 /test2.html 200 /test2.html 200 /test2.html 308 --> /test2 200 /test2.html 200 /test2.html
/test3/test3.html 200 /test3/test3.html 200 /test3/test3.html 200 /test3/test3.html 308 --> /test3/test3 200 /test3/test3.html 200 /test3/test3.html
/test4/ 200 /test4/index.html 200 /test4/index.html 200 /test4/index.html 200 /test4/index.html 200 /test4/index.html 200 /test4/index.html
/test4/index.html 200 /test4/index.html 200 /test4/index.html 200 /test4/index.html 308 --> /test4/ 200 /test4/index.html 200 /test4/index.html

完整测试

下列表格展示了完整测试的测试结果。下表以 Apache 为标准测试对象:

Apache GitHub Pages GitLab Pages Cloudflare Pages Vercel Netlify
/ 200 /index.html 200 /index.html 200 /index.html 200 /index.html 200 /index.html 200 /index.html
/index 404 (default) 200 /index.html 200 /index.html 308 --> / 404 /404.html 301 --> /
/index.html 200 /index.html 200 /index.html 200 /index.html 308 --> / 200 /index.html 200 /index.html
/test1 301 --> /test1/ 200 /test1.html 302 --> /test1/ 200 /test1.html 200 /test1/index.html 200 /test1.html
/test1.html 200 /test1.html 200 /test1.html 200 /test1.html 308 --> /test1 200 /test1.html 200 /test1.html
/test1/ 200 /test1/index.html 200 /test1/index.html 200 /test1/index.html 200 /test1/index.html 200 /test1/index.html 301 --> /test1
/test1/index 404 (default) 200 /test1/index.html 200 /test1/index.html 308 --> /test1/ 404 /404.html 301 --> /test1/
/test1/index.html 200 /test1/index.html 200 /test1/index.html 200 /test1/index.html 308 --> /test1/ 200 /test1/index.html 200 /test1/index.html
/test2 404 (default) 200 /test2.html 200 /test2.html 200 /test2.html 404 /404.html 200 /test2.html
/test2/ 404 (default) 404 /404.html 200 /test2.html 308 --> /test2 404 /404.html 301 --> /test2
/test2.html 200 /test2.html 200 /test2.html 200 /test2.html 308 --> /test2 200 /test2.html 200 /test2.html
/test2.html/ 404 (default) 404 /404.html 200 /test2.html 404 /404.html 200 /test2.html 301 --> /test2
/test3 301 --> /test3/ 301 --> /test3/ 302 --> /test3/ 404 /404.html 404 /404.html 404 /404.html
/test3/ 200 (Index of /test3) 404 /404.html 404 /404.html 404 /404.html 404 /404.html 404 /404.html
/test3/test3 404 (default) 200 /test3/test3.html 200 /test3/test3.html 200 /test3/test3.html 404 /404.html 200 /test3/test3.html
/test3/test3.html 200 /test3/test3.html 200 /test3/test3.html 200 /test3/test3.html 308 --> /test3/test3 200 /test3/test3.html 200 /test3/test3.html
/test4 301 --> /test4/ 301 --> /test4/ 302 --> /test4/ 308 --> /test4/ 200 /test4/index.html 301 --> /test4/
/test4/ 200 /test4/index.html 200 /test4/index.html 200 /test4/index.html 200 /test4/index.html 200 /test4/index.html 200 /test4/index.html
/test4/index 404 (default) 200 /test4/index.html 200 /test4/index.html 308 --> /test4/ 404 /404.html 301 --> /test4/
/test4/index.html 200 /test4/index.html 200 /test4/index.html 200 /test4/index.html 308 --> /test4/ 200 /test4/index.html 200 /test4/index.html
/404 404 (default) 200 /404.html 200 /404.html 200 /404.html 404 /404.html 200 /404.html
/404.html 200 /404.html 200 /404.html 200 /404.html 308 --> /404 200 /404.html 200 /404.html
/xx 404 (default) 404 /404.html 404 /404.html 404 /404.html 404 /404.html 404 /404.html
/xx.html 404 (default) 404 /404.html 404 /404.html 404 /404.html 404 /404.html 404 /404.html
/xx/ 404 (default) 404 /404.html 404 /404.html 404 /404.html 404 /404.html 404 /404.html
/xx/xxx 404 (default) 404 /404.html 404 /404.html 404 /404.html 404 /404.html 404 /404.html
/xx/xxx.html 404 (default) 404 /404.html 404 /404.html 404 /404.html 404 /404.html 404 /404.html
/test1/xx.html 404 (default) 404 /404.html 404 /404.html 404 /404.html 404 /404.html 404 /404.html

下表以 GitHub Pages 为标准测试对象:

Apache GitHub Pages GitLab Pages Cloudflare Pages Vercel Netlify
/ 200 /index.html 200 /index.html 200 /index.html 200 /index.html 200 /index.html 200 /index.html
/index 404 (default) 200 /index.html 200 /index.html 308 --> / 404 /404.html 301 --> /
/index.html 200 /index.html 200 /index.html 200 /index.html 308 --> / 200 /index.html 200 /index.html
/test1 301 --> /test1/ 200 /test1.html 302 --> /test1/ 200 /test1.html 200 /test1/index.html 200 /test1.html
/test1.html 200 /test1.html 200 /test1.html 200 /test1.html 308 --> /test1 200 /test1.html 200 /test1.html
/test1/ 200 /test1/index.html 200 /test1/index.html 200 /test1/index.html 200 /test1/index.html 200 /test1/index.html 301 --> /test1
/test1/index 404 (default) 200 /test1/index.html 200 /test1/index.html 308 --> /test1/ 404 /404.html 301 --> /test1/
/test1/index.html 200 /test1/index.html 200 /test1/index.html 200 /test1/index.html 308 --> /test1/ 200 /test1/index.html 200 /test1/index.html
/test2 404 (default) 200 /test2.html 200 /test2.html 200 /test2.html 404 /404.html 200 /test2.html
/test2/ 404 (default) 404 /404.html 200 /test2.html 308 --> /test2 404 /404.html 301 --> /test2
/test2.html 200 /test2.html 200 /test2.html 200 /test2.html 308 --> /test2 200 /test2.html 200 /test2.html
/test2.html/ 404 (default) 404 /404.html 200 /test2.html 404 /404.html 200 /test2.html 301 --> /test2
/test3 301 --> /test3/ 301 --> /test3/ 302 --> /test3/ 404 /404.html 404 /404.html 404 /404.html
/test3/ 200 (Index of /test3) 404 /404.html 404 /404.html 404 /404.html 404 /404.html 404 /404.html
/test3/test3 404 (default) 200 /test3/test3.html 200 /test3/test3.html 200 /test3/test3.html 404 /404.html 200 /test3/test3.html
/test3/test3.html 200 /test3/test3.html 200 /test3/test3.html 200 /test3/test3.html 308 --> /test3/test3 200 /test3/test3.html 200 /test3/test3.html
/test4 301 --> /test4/ 301 --> /test4/ 302 --> /test4/ 308 --> /test4/ 200 /test4/index.html 301 --> /test4/
/test4/ 200 /test4/index.html 200 /test4/index.html 200 /test4/index.html 200 /test4/index.html 200 /test4/index.html 200 /test4/index.html
/test4/index 404 (default) 200 /test4/index.html 200 /test4/index.html 308 --> /test4/ 404 /404.html 301 --> /test4/
/test4/index.html 200 /test4/index.html 200 /test4/index.html 200 /test4/index.html 308 --> /test4/ 200 /test4/index.html 200 /test4/index.html
/404 404 (default) 200 /404.html 200 /404.html 200 /404.html 404 /404.html 200 /404.html
/404.html 200 /404.html 200 /404.html 200 /404.html 308 --> /404 200 /404.html 200 /404.html
/xx 404 (default) 404 /404.html 404 /404.html 404 /404.html 404 /404.html 404 /404.html
/xx.html 404 (default) 404 /404.html 404 /404.html 404 /404.html 404 /404.html 404 /404.html
/xx/ 404 (default) 404 /404.html 404 /404.html 404 /404.html 404 /404.html 404 /404.html
/xx/xxx 404 (default) 404 /404.html 404 /404.html 404 /404.html 404 /404.html 404 /404.html
/xx/xxx.html 404 (default) 404 /404.html 404 /404.html 404 /404.html 404 /404.html 404 /404.html
/test1/xx.html 404 (default) 404 /404.html 404 /404.html 404 /404.html 404 /404.html 404 /404.html

结论

在最普通的 Web 服务的基础上,各个平台都加上了一些新的访问和跳转规则。测试结果反映出各个平台实现特性的逻辑和规则的优先级有一些区别(例如 /test1 既可以返回 /test1.html,又可以跳转到 /test1/,还可以直接返回 /test1/index.html)。洒家横竖看了半天,发现想做个简单易懂且全面的总结并不简单,无论用文字还是伪代码都只会越搞越乱,因此只能粗略总结一下,建议有兴趣的读者直接看原始结果。

各个静态网站托管平台的特性支持情况如下:

  • 列目录:全部不支持,访问 /test3/ 都会返回 404
  • 自定义 404 页面 /404.html:全部都支持
  • 省略 .html 访问 .html 文件:除 Vercel 外,全部都支持
  • 访问 /test4 直接访问 /test4/index.html:仅 Vercel 支持,其他都是先跳转到 /test4/

在 Cloudflare Pages 平台,访问所有 /path/to/index.html 都会 308 跳转到 /path/to/,访问其他 .html 文件也会通过 308 跳转去掉 .html 扩展名。根据洒家的理念,静态网站应该保持最大的兼容性,而不依赖任何平台的特性。无论把代码上传到任何平台、任何服务器上都应该可以正常访问,甚至直接在本地通过 file:// 协议打开也应该能正常访问。由于这种强制跳转特性,洒家不会选择 Cloudflare Pages 平台。

而 Netlify 平台在基本测试中也存在瑕疵。同时存在 /test1/index.html/test1.html 的情况下,访问 /test1/ 会先 301 跳转到 /test1,然后 200 返回 /test1.html 的内容,这和一般的预期不同。访问 /test1 的结果可以存在争议,而访问 /test1/ 则应该是想访问 /test1/index.html。再观察 /test2/ 的访问结果,在存在 /test2.html 的情况下,访问 /test2/301 跳转到 /test2,猜测访问 /test1/ 出现的现象可能是由于这个特性的优先级过高。

在 Vercel 平台,存在 /test4/index.html 的情况下,访问 /test4 没有跳转到 /test4/,而是直接 200 返回了 /test4/index.html。同时,我们又可以直接访问 /test4/index.html。同时存在两种路径层级的访问方式,这可能导致页面资源相对引用混乱。

从基本测试可以看出,只有 GitHub Pages、GitLab Pages 和 Vercel 符合洒家的基本标准。从完整测试可以看出,最接近 Apache 的是 Vercel,最接近 GitHub Pages 的则是 GitLab Pages。因此,洒家可能会用 GitLab Pages 或者 Vercel 替代 GitHub Pages。然而到最后洒家忙活的这一圈也没用上,因为洒家另外搞出了一套方案,改用 GitHub Actions 从公开仓库私密发布 GitHub Pages 网站,不用再换平台了。感兴趣的读者可以前往仓库 Phuker/phuker.github.io 查看这套方案。