2026-05-14 10:22:32
依旧是内部 MES 系统的二次开发,这次要添加的是一个 MES 物料流转时间报表及超时预警功能。
即,两个站点之间的流转时间统计分析。客户对工艺流程的两个指定站点的流转时间有要求。需要拉报表出来。支持导出 Excel。这个不是一个简单的报表,而是包含了设置管理功能,例如,指定某个产品的某两个站点之间的流转时间不能超过多少小时。其次才是不同设置规则对应的统计表格功能。
可以考虑用企业微信机器人消息的方式进行预警。
同时,在 MES 系统里也可以有一个预警消息的展示界面,显示所有当前处于预警状态的批次信息,方便生产人员查看和跟进处理。
群消息推送功能参考:
https://open.work.weixin.qq.com/help2/pc/14931
已添加的 Webhook 地址示例:
https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx
推送企业微信消息的功能,最好封装成函数,同时增加一个无需登录就能调用的测试 API,方便判断推送功能是否正常。
短期内推送过多企业微信消息,会触发企业微信接口的报错:{“errcode”:45009,“errmsg”:“api freq out of limit, hint: [xxx], from ip: xxx, more info at https://open.work.weixin.qq.com/devtool/query?e=45009”} 需要规避。
一个长假期回来,岂不是所有的批次都会报预警?如果有消息收敛机制,就不需要考虑这个问题了。
前提是,需要把收集预警信息与发送微信预警消息逻辑分离,做成两个独立的定时任务。如果不分离,就不方便做推送消息汇总。
消息收敛机制,新建一个定时任务,判断预警历史中没有处理的预警记录。每次生成一条企业微信推送消息汇总,将所有未处理的预警记录的批次号和预警类型进行汇总,生成一条企业微信消息进行推送。处理完成后,把对应的预警历史状态标记为推送成功。
由于是二次开发,而且拿不到原 MES 的代码,所以原 Oracle 的数据库我只开了一个只读的账号,不进行任何的写入和修改操作。新功能的数据都是放到新建的 MySQL 数据库中。这样,预警规则,及预警历史记录都存储到 MySQL 数据库中;流转时间报表则是通过同时查询 Oracle 和 MySQL 实现。
实现这个功能大部分时间是在梳理需求,和调整交互体验。用 GPT 5.4 实现的第一版近乎完美,只是有一些逻辑上的缺陷。但是,参考王建硕大佬视频里的说法,未来将不是软件 bug,而是需求梳理的问题,就是没有跟 AI 交代清楚细节,导致 AI 没有完全理解你的需求和意图。确实是这样。
但是,要把一个需求事无巨细的交代清楚,也是一件需要耐心的事情,或者是能积累好日常的规范,不至于重复的细节还需要再说明一遍。例如:
不过以后 github copilot 换成 AI credit 计费之后,怕是不能这样奢侈地使用 GPT 5.4 了,何况是提掏腰包买会员。
不知不觉这个总耗时不超过 3 周的 MES 系统,从完全不了解 300 多张数据表功能,到已经二次开发上线了 10 多项功能。我感觉已经很效率了。但是从日志看,每天的使用者也就是两个相关人员。
虽然交互上我觉得很满意了,但是因为用的人少,我又收获不到什么成就感。加之,开发这样的内部系统总归会被算作是成本,费力不讨好。领导毕竟都是冷血的动物(听闻嵌入式开发同事被生产部门推到其他部门,因为成本 hold 不住),这无可厚非,得多考虑能形成营收的功能,而不是满足于忙碌的状态。
2026-05-14 09:07:12
在公司内网部署了一套 ubuntu 24.04 Desktop 作为一个内部 MES 小服务器。但是在 golang 服务中调用企业微信机器人消息接口时报错:
Post “https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx”: dial tcp: lookup qyapi.weixin.qq.com on 127.0.0.53:53: server misbehaving
我印象中,还是第一次遇到这个问题。用了这么多云服务器都是 ubuntu server,以及 windows WSL 里安装的 ubuntu,好像这个错误是第一次见。
systemctl status systemd-resolved
看来一下,这个服务是正常运行的。
但是,
cat /etc/systemd/resolved.conf
配置文件里 DNS 一行是空的。改成 114.114.114.114 之后,重启服务:
sudo systemctl restart systemd-resolved
然后再次在 golang 接口中测试企业微信消息推送就正常了。
我印象中安装这个系统时,应该用过浏览器访问网站是正常的。为何在 golang 中就失败了呢?
使用纯 Go 的 DNS 解析器,它严格遵循 /etc/resolv.conf 中列出的 第一个 nameserver(这里是 127.0.0.53),如果该服务器返回错误(如 server misbehaving)或不响应,Go 解析器不会自动尝试其他 nameserver,直接报错。
我看了一下 /etc/resolv.conf, 确实里面只有一行记录:
nameserver 127.0.0.53
但是,为何修改了 /etc/systemd/resolved.conf 就能解决 golang 的问题呢?
还有第二个问题,如何通过 Linux debug 工具或者 golang 日志来打印出这个完整的 DNS 解析过程呢?这样就能更直观地看到解析过程。
未完待续!
2026-05-12 15:36:32
最近发现大佬王建硕的微信公众号又开始写文章,最近几篇都是关于 AI 的。这篇《SKILL.md 相当于 index.html》非常适合我这种菜鸟,文章链接:
https://mp.weixin.qq.com/s/psu7fLuqdDiiwHZ71I9DGQ
我大概看了一下第二个和第三个项目
我比较吃惊的是 Mac 上的自动化 shell 脚本还能这样写,大概率也是 AI 写的,确实超出人类的 shell 极限。
看看实际的 skill.md 比去了解科幻的项目要有意义多了。
我在 github 网页里问 copilot 这样自动化微信公众号文章的发布过程是否会导致封号。
其认为不至于,因为登录授权这些流程并没有自动化,只是把打开网页,复制黏贴部分自动化了。而且也不是单设备多账号的操作。问题不大。也是,之前有点多虑了。
2026-05-08 14:01:07
这周收到一个半导体产线 MES 系统的二次开发需求,即,增加一个 Hold 信息报表,展示预 Hold、在制 Hold、解 Hold 信息,信息展示包括时间、人、Hold 原因、解 Hold 解释、Hold 状态、类型等。
我大概理解是什么是 Hold 状态,但是这个预 Hold 又是什么呢?我查了一下。
在 MES(制造执行系统)里,Hold 通常翻译为 “冻结”、“锁定”或“留置”,我们这里叫“在制 Hold”。可以理解为:给一个批次或单个产品贴上“暂停流转”的标签。即,把产品挡在当前工序,阻止其继续生产、检验或发货。核心目的:在不确定产品状态时,防止不良品继续生产、减少损失,并争取决策时间。
举个例子,在我们的系统中,当某个工序站点的良率低于设定的阈值 98% 时,系统会自动生成一条 Event 事件,类型为 Hold,原因类型为 “出站良率低于设定值”。这个时候,这个批次就进入了 Hold 状态,无法继续流转到下一个工序站点,直到这个 Hold 状态被解除。
Hold 的典型应用场景
即,Pre Hold, 翻译为预冻结 / 预留置。在数据库中的状态字段可能是 Hold_P 之类的缩写。是在正式 Hold 之前的一种过渡性、预警性状态。它的核心作用是:在最终判定质量异常之前,先把物料“软锁定”起来,避免它继续流转,同时等待进一步检验或评审。可以把 Pre-Hold 理解为一种 “软冻结”(Soft Lock),而正式的 Hold 是 “硬冻结”(Hard Lock)。
我疑惑的点是,在我们的 MES 系统中,近 2000 个 Hold 状态,但是只有 2 个 Pre Hold 状态。而且看起来是第一次部署验收系统时的测试数据。感觉是使用人员对 Pre Hold 的概念没有理解正确。上面提到的系统自动将良率低于设定值的批次置为 Hold 状态,从概念上看应该是先置为 Pre Hold 状态,等待人工评审后再置为正式的 Hold 状态。我昨天特意问了一下产线人员,他们说直接设置为 Hold 状态,没有问题。我这里存疑。
这里有个对比表格,非常直观:

实际应用示例,场景:汽车零部件压铸工序
即,Release Hold, 放行。QA 或主管对 Hold 批次做评审,有几种处理方式:
对应的批次事件状态,即 Release 状态。
因为要实现这个 Hold 信息报表的前端展示,我担心数据并非跟我想象的一致,即,一条 Hold / Pre Hold 对应一条 Release 记录。如果不是一一对应的关系,我就无法通过 table 的一行来同时展示 Hold 和 Release 的信息了。所以,我特意查询了一下数据库,发现有一些奇怪的流转记录:
总体看上去,Hold 相关的功能,目前的使用人员还没有一套规范,导致数据看起来很奇怪。估计这也是找我开发这个 Hold 信息报表的原因吧。
2026-05-07 10:53:28
昨晚写代码到 22 点,本来想看会网飞讲 Spotify 的神剧《串流先锋 The Playlist》放松一下。突然接到一个客户的新开发需求。客户大哥说他文字表述不清楚,非要跟我视频,然后我就看他在办公室的大屏幕上手写计算公式,然后一点点说明计算逻辑。
突然感觉回到了大学课堂看天书般的数学课板书。不过好在遇到过好几个类似的需求,我大概也能猜出计算逻辑。所以,简单确认几个问题,就互道晚安。但是,大哥说了一句话,让我很暖心:
你是我遇到的技术人员中服务最好的!
我心想这可不是吗,哪个程序员会大晚上 10 点还笑嘻嘻地听客户讲需求。而且属于临时加需求,分文不多收。如果换了其他人早咆哮了吧。我甚至晚上 11 点参加过类似的多方需求讨论会,还帮客户的外包开发团队讲解计算公式。客户感动地要在我所在城市开分公司,让我跟着他干,但是我感觉并不是适合,就回绝了。但是总体感觉上,这些老板挺好相处的。特别是,他们能看到你的付出,也会直接肯定你的价值。
我很喜欢这样的合作。即便不收费,我也愿意去维护这些程序。但是,这些老板通常比较大方,会主动发红包。
而反观公司内部的系统开发,真是一眼难尽,昨天一上午灰头土脸地解决了两个不同项目的 5 个问题。一句感谢都没有。现在还面临被裁员,shit。这些事也不能强求,我尽量做好分内的事情。
不过,生活中多夸夸别人,确实是一个好习惯,得多加练习。
2026-04-28 13:09:47
昨天用 GPT 5.4 实现了一个内部 MES 的同类型设备的产出及良率的统计报表功能。因为这个 MES 系统是外购的,二次开发没有源代码的情况下,只能直接读数据库。在 349 张表的情况下,靠人工分析非常浪费时间,所以我找到相关的表之后,把表结构导出为文档,放到了 golang struct 的注释中,然后让 AI 去实现这个统计功能。这个过程中,总结了一些经验技巧:
没有命名规范,就很难定位具体的表存储。也没法规范 AI 的输出代码规范。包括英文的,也包括中文的。暂时我放到了代码项目文档里面,例如新建一个“命名规范.md”的文件,方便在团队中共享,或者仅仅是个人独立开发给 AI 看的:
命名规范
这里把一些常用的名称规范列出来,方便统一称谓,以及 AI 代码生成时的名称规范。
## 命名列表
- 关于 “MD” 的含义:最常见是 “MD = Master Data”,即“主数据”;也可能有场景把 MD 理解为 “Metadata(元数据)”,但在企业 MES 命名约定中通常指主数据(产品主档)
- 设备:MD_EQUIPMENT,EQUIPMENT 缩写为 EQP
- 良率:Yield,缩写为 YLD
- 批次:Lot,即 LOT
- ...
后续看看怎么放到 instruction 或者 skill 中。一个苏州来的 mes 销售公司来公司推销 mes 时,也特别说明了这一点,做 mes 系统首先要统一命名规范。
例如,一些统计,某些字段可能是空的,由于使用者没有填写,所以不能作为统计依据。而 AI 可能会忽略这些逻辑。而大量表存在冗余字段,也许存在别的表中,这就会导致统计逻辑取错表。
有些字段的原始命名存在歧义,很容易取错字段。修复只需要修改一个变量名单词,而要给 ai 描述清楚,则需要点功夫。就像我很难理解在扣子里添加待办日程,非得跟 ai 聊天,然后响应半分钟才能添加上。那我手动五秒钟不就加上了吗😳
所以,要警惕那些说靠 AI 完全实现开发一个完整项目的言论。毕竟新项目可以这么搞,但是历史项目不现实。
昨天快速上线了一版预览版本,今天上午就收到了 BUG 反馈。。。我觉得挺好的,总比憋一周才上线要好,半天上线收集反馈再迭代就好。