惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
The GitHub Blog
The GitHub Blog
小众软件
小众软件
美团技术团队
博客园 - 司徒正美
G
Google Developers Blog
Blog — PlanetScale
Blog — PlanetScale
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
大猫的无限游戏
大猫的无限游戏
罗磊的独立博客
Recent Announcements
Recent Announcements
酷 壳 – CoolShell
酷 壳 – CoolShell
D
Docker
J
Java Code Geeks
Last Week in AI
Last Week in AI
V
Visual Studio Blog
Microsoft Azure Blog
Microsoft Azure Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Proofpoint News Feed
V
V2EX
C
Check Point Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
MyScale Blog
MyScale Blog

竹林里有冰的博客

Nuxt SSG 博客的尾斜杠到底怎么加? | 竹林里有冰的博客 小米 Xiaomi Book Pro 14 (Ultra X7) Linux 兼容性实测 | 竹林里有冰的博客 国内(大陆)版小米 FCM 熄屏断连:Rootless 环境下的尝试与可能的解决方案 | 竹林里有冰的博客 我没法访问 dl.google.com —— 记一次 TUN 下的网络 debug | 竹林里有冰的博客 Vercel 的缓存控制,你注意过吗? | 竹林里有冰的博客 小记 —— Caddy 在 Layer 4 上的流量代理实践 | 竹林里有冰的博客 你的域名后缀拖慢你的网站速度了嘛?——再谈 DNS 冷启动 | 竹林里有冰的博客 DNS 冷启动:小型站点的“西西弗斯之石” | 竹林里有冰的博客 HTTP/2 Server Push 已事实性“死亡”,我很怀念它 | 竹林里有冰的博客 Nuxt Content v3 中数组字段的筛选困境与性能优化 | 竹林里有冰的博客 后 OCSP 时代,浏览器如何应对证书吊销新挑战 | 竹林里有冰的博客 初试 Github Action Self-hosted Runner,想说爱你不容易 | 竹林里有冰的博客 DNS 解析延迟毁了我的图床优化 | 竹林里有冰的博客 Vue Markdown 渲染优化实战(下):告别 DOM 操作,拥抱 AST 与函数式渲染 | 竹林里有冰的博客 Vue Markdown 渲染优化实战(上):从暴力刷新、分块更新到 Morphdom 的华丽变身 | 竹林里有冰的博客 node-sass 迁移至 dart-sass 踩坑实录 | 竹林里有冰的博客 前端中的量子力学——一打开 F12 就消失的 Bug | 竹林里有冰的博客 2025 年,如何为 web 页面上展示的视频选择合适的压缩算法? | 竹林里有冰的博客 el-image 和 el-table 怎么就打架了?Stacking Context 是什么? | 竹林里有冰的博客 2025年,前端如何使用 JS 将文本复制到剪切板? | 竹林里有冰的博客 ssh 拯救世界——通过 ssh 隧道在内网服务器执行 APT 更新 | 竹林里有冰的博客 Cudy TR3000 吃鹅(daed)记 | 竹林里有冰的博客 使用 Cloudflare Workers 监控 Fedora Copr 构建状态 | 竹林里有冰的博客 基于 Cloudflare Workers 实现的在线服务状态检测告警系统 | 竹林里有冰的博客 构建部署在 Cloudflare Workers 上的 TG Bot | 竹林里有冰的博客 2024年,Firefox 是唯一还在坚持执行在线的 SSL 证书吊销状态检查的主流浏览器 | 竹林里有冰的博客 小爱课程表适配不完全指北——以 ZJUT 本科正方教务系统为例 | 竹林里有冰的博客 将博客从 waline v2 更新到 waline v3 | 竹林里有冰的博客 给家里云装上 Fedora 41 KDE 后,我是如何配置的 | 竹林里有冰的博客 为 Hexo 添加 follow 认证 | 竹林里有冰的博客
使用向日葵智能插座 C2 用电记录推算宿舍上次烧水时间 | 竹林...
竹林里有冰 · 2024-09-24 · via 竹林里有冰的博客

我宿舍里入口处有一张公用的桌子,上面有一个烧水壶。根据生活经验,当用手摸烧水壶外壳能感受到明显热量时,水壶内的水大概是两小时内烧的,绝对能喝;但如果用手摸烧水壶外壳感受不到明显热量时,水壶内的水就不知道是什么时候烧的了,可能是三小时前,也可能是三天前。此时,在不寻求外部科学仪器介入的情况下,唯一能做的是询问寝室成员上一次水是谁烧的,是什么时候烧的。但寝室成员并不总是能够及时回答,可能在睡觉,也可能不在寝室里,还有可能出现记忆错乱。

因此,我们需要一种可靠的方案获取上一次烧水时间。

前两天陪黄老板出门吃宵夜的时候和他提到了这个难题,我提出在烧水壶附近加装物理按钮,按动时向局域网内的 HomeServer 发送请求记录准确的烧水时间。他提出可以在烧水壶前加装智能插座,使用智能插座的耗电量来推算上一次烧水时间。这是一个可行方案,上次烧水时间不需要分钟级的精准度,小时级的精准度在这个需求上完全够用,这是一个更好的方案。

在「使用 Root 后的安卓手机获取向日葵智能插座 C2 的开关 api」这篇文章中,我有过抓包向日葵官方 app 的流量数据的经验,这一次直接故技重施。很可惜,我发现用电量数据并不能直接从局域网内向智能插座获取,必须要从向日葵官方的服务器拉下来。其实想想也知道,用电数据一旦精确到小时级,日积月累下来会对硬件的存储提出一定的挑战,而比较合理的方案就是由硬件向官方的服务器每小时通信一次记录下来。

抓包抓包

不过好消息是,官方服务器的这个接口并没有进行鉴权,不需要进行额外的操作,一条 curl 命令都能下载下来。

curl 命令下载用电量数据curl 命令下载用电量数据

https://sl-api.oray.com/smartplug/powerconsumes/${SN}

SN 码也不需要自己去抓包,直接在官方应用的设备关于页面就能看到。

关于页面关于页面

json 数据的结构很明显,最外层是一个 Array,里面有若干个 object

[
  {
    "consume": 0,
    "starttime": 1727125200,
    "endtime": 1727128740,
    "index": 0
  },
...
]
  • consume: 这段时间消耗的用电量,单位 Wh
  • starttime: 开始时间,unix 时间戳
  • endtime: 结束时间,unix 时间戳
  • index: 智能插座的第几个孔位(为插排预留的参数,智能插座只有 0 这一个位置)

所以我们要做的就是每小时下载一次这个 json 文件,需要时从 json 中寻找上一次用电量较高的小时,取那个小时的 starttime 时间戳转换为东八区人类可读的时间即可。

def last_water():
    with open('power.json', 'r') as f:
        powers = json.load(f)
    for i in powers:
        if i.get('consume') >= 30:
            t = i.get('starttime')
            break
    last_water_time = datetime.datetime.fromtimestamp(t)
    now = datetime.datetime.now()
    time_delta = now - last_water_time
    sec = time_delta.total_seconds()
    hours = sec / 3600
    lwt_str = last_water_time.strftime('%m月%d日%H点')
    return f"上次烧水时间为「{lwt_str}」,距离现在「{hours:.2f}」小时"

至于每小时下载的任务,我这里是使用 crontab + curl 命令实现的,用 python 写个死循环跑也可以。

那么数据都取到了,剩下的就是人机交互的部分,这部分夸张点的可以写 web,写小程序,甚至写个安卓应用挂个桌面插件,想怎么做都可以。我这里就单纯将数据接入 qqbot 扔到了宿舍群,简单写了个关键词触发。

宿舍群宿舍群