代码 | Coding

  • 很久没折腾 Home Assistant 了,近期从范老师那里收到了一款很好玩的内测产品 Sleepal,可以通过 Matter 协议接入 HA,通过非接触的方式监测睡眠状态。可以在 HA 拿到入睡状态,近而实现一些原来不能实现的自动化,非常有趣,分享一下。

    包装盒不错!

    首先说一下 Sleepal AI Lamp

    不知道中文名叫啥,睡宝?睡灯?… 睡登?😂

    之前 Webto 还在范老师那搬砖的时候参与过这款产品,那时我正被睡眠问题困扰,之前听他聊起来就非常感兴趣:

    • 放在床头,不需要佩戴,即可像 Apple Watch 一样跟踪睡眠。
    • 睡眠分析:通过手机的数据结合 AI 给出睡眠的改善建议。(最早我记得是说基于 CBTi,这部分还没体验到。)
    • 哄睡功能和无痛唤醒,具有 RGB 氛围灯和白噪音音箱。

    具体的原理是通过配备的毫米波雷达点阵热阵列传感器声学传感器来跟踪身体数据,同时通过收集环境光温湿度信息评估睡眠环境。

    “MI Style” 的设计风格

    我拿到的测试版,实际用起来的感受就是睡觉不用佩带 Apple Watch,也能拿到和 Apple Watch 一样的睡眠数据了,数据也可以同步到 Apple Health。准确度上我感觉和 Apple Watch 差不多,同时会提供一些比 Apple Watch 更详细一些的维度,比如睡姿、睡眠环境分析等。我测试的重点主要是 HA 连动,更详细的功能介绍可以去看产品的众筹页面官网

    Sleepal 传感器图 via KickStarter
    传感器原理图,图源 KickStarter

    首个可以接入 HA 的非接触入睡传感器

    先加足够定语叠个甲,因为接触式的似乎有 Withings Sleep 以及个别自制方案。非接触式做到 Apple Watch 精准度的完整产品应该是头一个?

    睡的还行,但好像暴露了昨晚打鼾的事实好羞耻… 😳

    Sleepal 支持 Matter,可以通过 Matter 方式接入 HomeKit 和 Home Assistant。具体方式是通过 Sleepal App > 我的 > 我的 Sleepal > Matter ,打开配对即可开启。因为目前 Matter 功能还在内测,所以传感器还没有整理,目前可以得到有效的 HA 实体:

    • 一个light实体:控制 Sleepal 的灯光,目前支持亮度、冷暖调节,RGB 的部分还没有接入。
    • 一组binary_sensor实体:入睡状态、在床状态、起夜监测、助眠状态、闹钟和 Snooze,以及还有一些不知道作用的实体
    • 一组sensor实体:环境温度、湿度、照度

    Matter 进 HomeKit 时,表现为灯光和一组人在传感器

    目前 Matter 与 HA 的开发还比较早期,可以看到 Vendor 和 Device Name 还是 TEST

    目前对我比较有用的实体就是入睡状态在床状态

    入睡传感器,是一个非常有用的自动化 Trigger!

    一天最重要的生活场景转化发生在卧室,我的卧室就有非常多的自动化,它们围绕着入睡与醒来。比如入睡前播放助眠音乐,调暗卧室灯光,开启环境家电与卧室外的监控摄像头。或者醒来时开启窗帘,调整灯光场景等。

    其中一些场景可以主动触发(如语音指令或按钮),或者做基于时间触发的自动化。但一些场景就比较麻烦,比如睡着后关闭助眠音乐 – 因为你无法在睡着的时候告诉 HA 你睡着了 >_<!

    之前有关人的状态就只有人在传感器与运动传感器,它们都无法分辨入睡状态,有了入睡/醒来状态,思路一下就打开了。分享几个我最近用的有趣的场景。

    Sleepal 入睡传感器 HA 截图
    入睡 / 醒来 状态的二元传感器

    💤 睡着后,关闭 🎵助眠音乐,关闭 💡主卧灯光

    之前失眠耳鸣给自己找到的哄睡办法是 HomePod 播放助眠音乐,同时主卧将灯光调到舒适的暗调。通过一个倒计时逐渐调低音量和灯光。Time Based Rule 的问题就是有时没睡着音乐停了,或者睡着了又给吵醒了。入睡传感器完美解决了这个问题。

     睡着后,关闭 助眠音乐,关闭 主卧灯光 Home Assistant 截图
    推荐我一直用的一个 Apple Music 助眠歌单:Sound Bath 非常好睡…
    再推荐一下我的 Nanoleaf 木纹奇光板吧!我用它模拟睡前摇曳的烛火氛围。

    💤 入睡后,开启摄像头。🛏️ 起夜 或 🌞醒来时,关闭摄像头

    卧室外有几个小米摄像头做出差看家。有了入睡检测后,可以在睡着后也自动开启。醒来时关闭,避免拍下衣衫不整的自己 😳。

    看家模式的脚本,会打开卧室以外的所有摄像头,并给手机发送通知已告知摄像头打开了。

    🌞 起床后,关闭环境电器,自动开灯

    原来我的主卧新风、加湿器与空调都是基于定时关闭的,现在可以时间更酷的自动化。我的厨房和餐厅是我早起洗漱后第一个要去的地方,我新家了一个自动化:起床后,如果阴天的话,帮我开启餐厅的射灯。新的一天还是要有一个明亮的开始!

    脚本说明:我餐厅四个角有 4 盏射向天花板的,我让它们根据太阳的入射角sensor.sun_solar_azimuth 来独立调整亮度,让光源模拟真实太阳光的方向,以实现更好的清晨唤醒效果。✌️

    variables:
      solar_azimuth: "{{ states('sensor.sun_solar_azimuth') | int}}"
      is_evening: >-
        {{ ( solar_azimuth >= 0 and solar_azimuth < 90 ) or ( solar_azimuth > 270
        and solar_azimuth < 360 )}}
      light_1_brightness: "{{ ((solar_azimuth - 270)/180) | abs if is_evening else 0 }}"
      light_2_brightness: "{{ (1 - light_1_brightness) | abs if is_evening else 0 }}"
      light_3_brightness: "{{ 0 if is_evening else ((solar_azimuth - 90) / 180) | abs}}"
      light_4_brightness: "{{ 0 if is_evening else (1 - light_3_brightness) | abs }}"

    更多好玩的可能性…

    还有更多的可玩之处,还没有来得及实验,准备旅行回来试试。比如:

    • ❄️ 空调控制:根据入睡时长动态调整温度风速。Sleepal 的温度传感器离你最近,所以也可以代替空调自身的温度传感器,实现更接近体感的空调温控。加湿器同理。
    • 💡夜灯模式:起夜离床时,提前打开卫生间夜灯,甚至提前掀开可红外遥控的马桶盖(如 Toto 的 CES802CS),躺床后自动复原,实现更前置灵敏的夜间卫生间整备。

    目前的内测版上随着 Matter 接入 HA 的实体有好几个保留项未被定义,不知道未来是否会开放更多。心率呼吸应该是在设备端比较容易,睡眠评分可能是在 app 端生成,不知道是否能够同步 HA。它们能够开放的话,甚至可以通过睡眠质量来进行自动化控制,比如“睡的不好的话,早餐 BGM 自动挑选更轻松的唤醒歌单”。

    总之,这是一个非常好玩的产品,也是目前我最能接受的睡眠监测的形态。同时可以带给我很多关于 Home Assistant 控制的新灵感和新思路。产品据说已经开发三年,团队也是「小米人在传感器」的开发者,非常靠谱。目前众筹中,应该可以邮国内,欢迎支持一下范老师哇。

  • 写了一个自用小项目

    ·

    最近闲下来,开始关注最近比较火的 AI 新闻。感觉这几个月,世界变化真的太快了,有一点愚蠢的人类,终于开始掌握魔法的感觉😄。关注开发者社区,尤其是 openai-gpt3.5-turbo 出来之后,感觉每天都有人 commit 新项目。而我每天的聊天量,感觉和 chatGPT 聊天的数据量已经大过了我和真实人类(和人类聊天本来也不怎么多)。

    这种情况即让人好奇,又让人焦虑,仿佛站在时代变化的当口,又不知道该何去何从。和行业里的朋友聊天,大家都说以后一个人就可以开一个项目,也有人说开一家公司只需要 import openai

    对于不了解的东西,往往试一试才知道(我鼓励所有的产品经理都要能自己写一点代码)。前一阵我在 5 年来第一篇更新 中提到,最近开始重拾基于 RSS 的长内容阅读了,有一些非常不错的英文财经博客,读起来还是很吃力和费时的。所以就在想能不能 import 一下魔法。我不是开发者,在春节左右我才开始了解 Python 编程,所以也在想试试能否在 chatGPT 的帮助下写一个能用的项目。

    写了一个自用小项目

    经过几天的零散时间,我完成了这个叫做 OpenAI Feed Trans 的小脚本:将我订阅的英文博客 RSS,使用 OpenAI 的 API 进行翻译,并保留所有样式生成一份新的 RSS Feed,供我自己订阅。

    OpenAI Feed Trans 的 Github 截图

    尝试让 chatGPT 帮我完成代码

    最开始的想法是,是否可以将我的整个脚本交给 chatGPT 完成(因为功能实在是非常简单)。于是我非常详细的和 chatGPT 说了一下我的需求,以及定义了我要的输入输出。这货非常快的给了我结果,但是… 指望它直接可以 run 起来,果然是不行的😓。

    但非常有效率的是,我可以自己将脚本的整个框架搭起来,然后让 chatGPT 帮我快速完成一些函数。比如

    帮我使用 python 完成一个函数 def splits_content(content, max_tokens): 输入是一个名为 content 的字符串,字符串中通常包含了 html 语言的代码片段。函数的的作用是将这段文本拆分成不大于 max_tokens 的字符串数组,并返回这个数组。注意,在拆分字符串的时候,不能够将一句完整的句子拆分,遇到这种情况把这句话放到下一个分组。同时也不能拆散 html 标签。如 <p>test</p> 不可拆分为 <p>test</p>,只能是<p>test</p>。请给出一个简洁的示例代码。

    然后这货真的可以把代码写出来,并且偶尔给你示例的输入输出。但是需要注意的是,它给出的代码往往会包含很多 bug,这时候你连着预期输出或报错信息,它会抱歉后为你提供一份新的代码。运气好的话,你就可以得到一个真正能用的函数。在我的项目里,拆分段落的函数,基本就是原封不动 gtp 帮我写的,注释都写好啦。

    而对于不太常用的第三方库,chatGTP 会表现得错误百出,比如 feedparser 模块相关的代码,就真的调不好了(我甚至劝它好好读一读文档)。因为我是 Python 新手,chatGTP 对我最大的价值就是我不用读完整本编程指南。我想做什么,可以直接让 chatGTP 帮我写示例,对于不懂的地方,让它给我做详细的解释。

    我觉得这是一个非常快的学习路径,比我自己翻 doc 快太多。未来可能交互式学习法会大有可为。

    同时,我还可以让 chatGTP 帮我去完成润色我的一部分注释,我的项目 README.md 就是它帮我完成的英文版本。

    通过 openai-rss-trans 翻译订阅源
    通过 openai-rss-trans 项目对 RSS Feed 进行翻译,只翻译文本,可以保留 RSS 内置的样式、链接和图片
    内容来自 Webto 推荐给我的一个内容很好的 IT财经 blog, Ben Thompson 的 https://stratechery.com
    阅读器为开启 BR 模式的 Reeder

    顺便说说 OpenAI Feed Trans

    这是一个非常简单的小脚本,因为我也是新手,就不写编码教程了。简单分享一下思路:

    1. 使用 `feedparser` 模块做 feed 解析 ( https://feedparser.readthedocs.io/en/latest/ )
    2. 将每个 Entry 分割成小片段,这样每一次的 openai 请求不会超过最大 tokens
    3. `import openai` (使用魔法)对每一个片段做翻译。Prompt 大概意思就是:将内容中的英文替换成中文,
       只替换内容, 不要破坏html标签和结构。通过这样的指令,保留 RSS 内的 HTML 标签和样式正确。
    4. 将 feedparser 的 feed 字典转换为 `feedgen`( https://feedgen.kiesow.be ) 的数据结构,使用 feedgen 保存新 feed
    5. 处理 cache,因为每次请求都是要耗费 tokens 的,所以把翻译过的内容做缓存

    如果你也有 RSS 阅读的习惯,也订阅一些外文 feed,自己有 www 服务器,欢迎速食… 🍚

    Log 大概长这样… 凑合看

    闲聊两句

    最近和每个朋友聊天,都避不开最近的 AI 话题,总之 “人类又有新的自行车了”这件事一定是必然,变化也是必然的,这件事情想想让人兴奋。我感觉未来的 6 – 12 个月,很多事情都会翻天覆地的变化,那么我们在这个变化中能做点什么?做点什么有价值,又不是去投机地赶一个新的时髦?还不知道。

    上一周憋在家里上网冲浪,没有冬天的时候逛公园逛的勤快,百望山的花儿开了,下周可以踏踏青。

    一张几个礼拜前在圆明园拍的照片,下周再去看看,估计这一片已经开始冒出绿色了:)

    圆明园的一片空地
    圆明园的一片空地,人很少,可以满地打滚… by Frish

  • 标注一下最近的coding study

    ·

    前一阵,立志再忙也要 Keep Coding,于是基本每天都会睡前看会儿文档,或者做一些练习。

    想到一个有趣的便签App 的原型,比较适合练习代码,能够自定义界面,然后与 iCloud 同步。

    然而掉进了一个大坑,简单标注一下。等春节闲了,再说说研究成果。:D

    1.开始自然想到用 UIDocument 的方式来实现,于是翻了遍文档,写 iCloud sync 的部分的时候,发现对于一个便签来说,非常不优雅。最费解的是,如果想预览、更新 iCloud 上文档的内容时,不得不执行 document.open 操作,然后文件的修改日期就更新了,没法按照正常的修改日期排序。而且异步save时也除了很多挠头的问题。

    2.于是又翻了几天 Core Data,基本弄明白了怎么工作,也写了一个简单的本地原型。后来翻了老半天也找不到如何集成 Core Data 到 iCloud,官方文档只是说可以看看 Programming Core Data with iCloud,开发者中心翻了个底朝天也没找到。

    然后在一个哥们的 gitHub 上才看到,说 iOS 10 以后,相关的方法都 Dispatched 了,以后 apple 可能不支持 Core Data 对于后续 iOS 版本的 iCloud 集成。

    3.今天睡前开始研究 CloudKit,但是之前 stackoverflow 上一个大哥说,CloudKit 只是针对 always online 的情况,如果断网,本地的数据不能用。如果映射一个 CloudKit 的数据到本地的 Core Data 也非常麻烦。

    恩…

    还是先研究一下 CloudKit 再说,如果逼到必须自己搞一个服务端…那我就先写点别的-.-

    找到一篇 CloudKit 说得比较明白的入门帖,周末在家研究研究:

    https://medium.com/@guilhermerambo/synchronizing-data-with-cloudkit-94c6246a3fda

     

     

  • 懒更了好久,都快忘了我还有这么个博客了😅今天睡前更了一下,也算2018写过blog了。

    最近的周末和晚上,基本都Keep coding了,每天都写很多bug😅,然后看很多文档。就这周,在研究iCloud与代码的交互,快搞死了。

    然后忽然想到一个显而易见的问题:为啥iOS的生态上,精致的Apps特别多,牛逼的有追求独立开发者特别多?

    原因当然有很多很多。比如Apple说“赋予人们更大的能力”,还真不是拍几条人文主义TVC,在商店卖一些创造类设备而已。说Apple封闭,对于(我这种)入门开发者提供的各种API、SDK,让设备能力很容易通过代码转化为Apps的能力,比如去年开放的CoreML和ARKit,让开发者把精力可以放在Idea的层面。

    然而我想说的也不是这一点(铺垫真长…)。

    最近不是coding iCloud based document的部分嘛,我忽然发现,如果没有iCloud服务,想做一个支持云同步的便签,或者将用户偏好进行云同步的app,那除了做app本身的编码,我还要做什么呢?

    我需要租一个虚拟主机,或者第三方云。

    我需要为服务器充值续费。

    我需要选网通线还是电信线。

    我需要维护服务器。

    我需要花一个礼拜翻php,学sql。

    然后再花一个礼拜进行服务端的性能优化。

    如果app火了,我要升级服务器、优化服务端。

    ………

    其实我只不过想写一个好用的便签,并且支持云同步而已。

    以上,可能是任何一个(个人)开发者都觉得再正常不过的事情了,然而好的设定,正是打破这种理所当然。

    让开发者关注创意本身,做自己擅长的事情,这是一件很幸福的事情。

    难怪在iOS上有IA Writter,有Day One这样能把一个小需求做得很美的Apps。

    (当然关于跨平台、和iCloud本身服务性能也有很多问题,这里先说好的一面)

    //我在想,如果Android在开发者生态上下功夫,会不会有另一番局面。亦或者MIUI或MIIoT,可以沿着这个思路,把特长变成规模,最后成为一门生意,会不会也是一条路径?

    ———

    最近真是失眠严重,睡了睡了…🤮

  • 好像又好一段时间没有写结绳记事。一是因为最近没发生什么大事,第二个是最近的时间都被占满了。春节一回来,工作日忙得跟狗似的,感觉比年前那段疯狂的时间更甚。周末的时间迷上了写代码。

    说到写代码,好像都是放下了快十年的爱好了。春节无聊读了读IOS编程的一些东西,得益于苹果已经把开发包装得足够简单,对于我这种十年没写过代码的人还算可以上手。边看春晚和春晚重播读了80多页的developer guide,跟读科幻小说一样欢乐。回来手痒就开始写点东西。

    对于我这种初学者每写一行代码都会遇到很多问题,很感谢网络上很多大牛分享的一些学习笔记。所以决定有时间也要把我遇到的一些简单可笑的问题总结一下以示后人。当然,前提是有时间。

    周末照例是装修日 + 代码日。一个恼人的bug折磨了我周六晚上好几个小时的时间,好吧 说正事儿。

    =====开始说正事儿的分割线======

    最近在写一个使用SpriteKit的IOS小游戏联系。在模拟器上运行都没什么问题,真机调试的时候,每次回到HOME的时候,就是applicationDidEnterBackground的时候,程序就会Crush。

    报的错误是main.m中 Thread1:EXC_BAD_ACCESS(code=1,address=0x1)。网上搜了一下大概这种问题是ARC错误release的对象再次被release。花了几个小时挨个方法注释代码,终于发现当运行SKAction的-playSoundFileNamed: waitForCompletion: 方法时必出现这个错误。

    后来终于在万能的SteakOverFlow找到了遇到同样问题的人,解决办法也在同一个帖子里。

    答案在这里http://stackoverflow.com/questions/18976813/sprite-kit-playing-sound-leads-to-app-termination/21349677#21349677

    简单的说,是因为-playSoundFileNamed: waitForCompletion: 用到了AVAudioSession类,当应用进入背景运行时,AVAudioSession 必须是非激活的,否则就会报错。然而SpriteKit在播放声音是并没有对其进行处理。解决办法也很简单,就是在应用背景运行时将AVAudioSession设置为inActive,应用回到前景时,重新设置为Active。

    具体的处理方式这里就不当搬运工了,大家去看讨论原文吧。