2024/4/8 00:06

我的技术生涯(2021-2024)

琴小站 ★

Offer

在到达第二家公司面试之前,我和女友拖着行李箱在附近兜兜转转都没能找到公司入口,最后仔细询问后终于找到了图中那条巷道,图是全景地图里截的,走进去后看到一栋比较老旧的厂房楼,当时已经是下午六点多,由于是冬季天色很快就暗了下来,加上那个奇怪装饰的货梯入口,货梯内大片的红色油漆以及已经损坏一闪一闪的照明灯,给这趟面试添上了几分诡异气氛。



老旧货梯运行速度很慢,到达四楼转个弯看见走廊两旁各放置一列钢琴,红地毯从走廊入口一直延伸到了公司的入口玻璃门,产品经理何哥过来接待了我,进入公司后引入眼帘的就是一间琴小站琴房,何哥向我介绍这是他们的第一代琴房产品,目前已经改进了一个版本并且投放在了三个小区内。这块区域几乎堆满了钢琴,往里还有一个空间很大的音乐厅,办公室只是在琴房旁边隔了两个小玻璃隔间,每个隔间可容纳5人办公,人事、市场、财务、研发混在一起没有区分部门,实打实的小公司,公司是为琴小站这个项目于2018年5月刚成立的,在此之前,这块场地是主营钢琴销售与二手钢琴回收翻新业务的钢琴厂,其中一位股东也就是现在这家公司的CEO刘总。目前这个阶段相当于两家公司共用一块地方,直到年后才在隔壁装修了新的办公区。

何哥把我带我到了音乐厅里坐下来正式面试,我先将自己的一些信息介绍后,他给我展示由外包开发的系统,据说花费五六十万,前端是微信小程序,总体效果挺丑的,交互体验更是难以言说,后端方面全部采用PHP开发,接入硬件部分用到了swoole,展示结束后,我取出带过来的笔记本将我的作品和技术栈也展示了一遍,何哥点头表示十分满意,然后提出了一个想法:重构整个琴小站项目

我在之后深入了解后发现这不是一件简单的事情,这个项目刚起步几个月不到,除了设计师没有招聘其它技术人员,而且现有项目从软件到硬件均存在很多问题,这时重构会花费大量的时间精力,理论上不应该进行如此冒险的行为,但初生牛犊不怕虎,正想找个有点难度的项目挑战一下,刚好还是我比较喜欢的软硬通吃项目,所以在一天后接到Offer通知时就直接答应了,试用期薪资只有8K,3个月转正后加到9K,转正后才有五险,薪资在一年后涨到10K,在第二年提离职时涨到18K,全年单休,朝九晚六(然而回到家里还是在赶项目进度),满一年起步才可以有5天年假,虽然薪资一直低于我的期望还时常拖发工资但还是坚持到第三年底才辞职。

入职

入职前一天我把生活用品和屏幕、机箱等等收拾好,出发前往深圳的亲戚家寄住,小时候就经常去那里玩,他们也是几乎一路看着我长大的,对于一个初入社会的人有这么个港湾瞬间就没有了异乡漂泊感,也算是有了一点先发优势,毕竟前期不需要考虑租房压力甚至晚饭都解决了,说实话一直白嫖吃住我自己是非常不好意思的,随着工作收入逐渐稳定下来,已经寄住一年左右后的我决定搬出去和女友一起租房住,虽然后面出去住了他们也经常叫我过去吃饭过节,很感恩。

2018年12月3日那天早上我准时的到达了公司,没想到来得有点太早,公司门都还没开,在楼道等半小时左右人事终于来开门了,我推着装了主机和屏幕的行李箱走进了我的工位,考虑公司起步阶段需要省资金就没有要求提供资金给我配台主机也不要求给机补,就自带之前配的ITX主机过来了,怕电源插口不够用还把排插也带上,一顿折腾算是把工位搞定。

当时我的左边是财务,对面是设计(后面为了聊产品方便换到了我左边),左斜对面是市场,我们在一张四连桌上,右侧是产品独立工位,目前为止还没能见到老板一面。

产品分解

既然想要重构,自然是先需要把现有项目的功能进行分解研究,跟何哥要来了所有的源代码的相关平台账号,由于是外包所开发,前后端源代码都比较混乱,甚至还混杂了用于其它项目的代码和注释没有删除,看样子是批量定制的外包方案,下面是大概先描述一下接手时的项目状态,这个项目由于起步时各项基建都极度缺失,导致后面重构时面临水桶效应,使得重构进入一种近乎无底洞的状态,最后迫不得已软硬两手抓把水桶的木板尽量补齐,这样项目的技术水平才能够上得来,这一系列经历在后面都会有涉及到。

C端

产品的C端部分是一个微信小程序,由于这一版本设计也是外包的所以整体设计粗糙、交互糟糕,存在多个Bug且时段选择比较死板,后台维护功能也是放在这个小程序中,最奇葩的莫过于这个Logo在圆框内的比例也太奇怪了吧,然后给改成右边这个样子,我是一个有完美主义倾向性格的人,否则可能不会轻易答应重构

C端主要逻辑就是用户扫描琴房屏幕显示的二维码,引导公众号关注后再进入小程序的对应琴房选择时段预约琴房,到达使用时间时用户就可以点击开门按钮控制琴房玻璃门解锁进入琴房并且空调与灯会自动开启,当使用时间结束时琴房的空调和灯会自动关闭,以下是它的部分截图。


B端

产品的B端部分是一个基于FastAdmin(ThinkPHP5+Bootstrap)框架的后台系统,体验上整体中规中矩,包含各种常规CURD操作,作为一个只给内部人员使用的系统确实是没问题的,但最核心的琴房控制功能却没有提供,并且依然存在一些BUG,依然需要在C端小程序中授权进入,从这到之后准备重构的后台系统来看,公司内部几乎所有人员是不愿意一直待在电脑前面的,所以在后期我直接把B端定位在快速易用的小程序上,这样不管处于何时何地都能管理琴房和订单,框架没啥大问题,糟糕的地方还是在外包写的代码中:函数命名混杂混入了其它项目的命名但却实在在为现在这个项目运行,也自然少不了英文拼音混合无驼峰或无下划线命名等、代码注释大量缺失或混杂,导致在修改功能时找代码10分钟修改10秒钟,只能不得不补充一些注释插眼方便查找。

机器云

机器云是负责接入控制板硬件和服务器通信的部分,依然是使用PHP编写,PHP本身是单线程的,为了应对这种实时通信场景这个部分就用到了Swoole(支持多种协议的异步、并行、高性能网络通信引擎),硬件方面为了在弱网环境下仍能维持较好的通信采用了UDP协议,毕竟TCP协议还需要三次握手才能完成连接,而UDP并不需要建立连接即可发送数据包,虽然存在丢包的可能,这时候重试机制就十分重要,但在机器云的代码中并未发现重试部分的代码,当控制板处于弱网环境时,机器云发出指令数据后就会一直等待响应直到无响应超时,这也导致后续的指令无法处理被阻塞,等待指令响应是通过不断检查是否存在响应的Redis记录值却不是使用回调函数这也让性能大打折扣,因此我们维护琴房时也不敢同时控制琴房还得控制手速,尽量确保一条指令下发完再进入下一条,除了这些问题外就还是代码混乱、请求参数无检查就发给硬件等等。

琴房硬件

接着就是琴房硬件部分,这位选手更是重量级,当我了解到这时震惊的发现此方案原始得不像智能琴房,从某种程度上就是一只缝合怪,能做成一套产品确实不易,最开始应该也是外包的方案,但该方案基本是为室内环境而打造的,除琴房本体结构和钢琴外主要由控制板、电插锁、门锁开关、插排、电梯空调、排气扇、安卓盒子、32寸显示屏、“工业级”4G路由器、杂牌网络摄像头、照明灯、USB插座构成。琴房结构上也存在问题,第一代琴房如上面的图片是有钢制顶棚的,但后续生产的琴房都取消这个顶棚了,原因是它非常笨重,至少需要三个人才能勉强抬升不利于维护,取消掉还能降低点成本,室外琴房就改用不锈钢架上有色半透PVC顶棚,为了维护方便拆顶棚还空出一条大缝隙,其它在架空层或有点遮掩的琴房是没有顶棚的,这就导致顶部会大量积灰,遇到大暴雨或台风天就会有雨水通过缝隙瓢泼进琴房顶,雨水和灰尘混合后变成了良导体,加上布线混乱还采用插排接线,容易引发漏电甚至短路,漏保跳闸几乎是家常便饭,也幸好能跳闸不然对用户来说是十分危险的。




控制板采用12V直流电源供电,主控是一颗STM32F103RBT6,它旁边是一颗SIM800C的2G通信模组以及SIM卡插座、天线SMA接口,还有一片EEPROM用于存储配置信息,黑色圆柱状的是一颗蜂鸣器用于产生刺耳的“嘀”声来提醒用户,有两路继电器分别是用于控制照明灯和电梯空调的通电或断电,还有用于控制12V电插锁电源通断的MOS管以及判断电插锁状态的接口,最后就是用于判断房内门锁开关是否按下的接口。整体用料不太给力,不过考虑到需要节省成本倒也没啥,但是一块控制板要价60多,当时芯片价格还不像现在这样直线疯涨,批量生产的成本是很低的,利润空间属实大了。功能方面,只有两路继电器但实际需要控制的还有房内的几个插座和播放广告的盒子和显示屏等的电源,因为缺失插座控制就经常会有人插用电器在使用时间结束后还在插座上白嫖电源,而且为了防蚊还配上了电子蚊香液,蚊香液是消耗品,无人使用时也在24小时工作蚊香液一下子就消耗光了,所以至少用户插座这一路的缺失是比较严重的,继电器这一侧的强电接口也是容易变形松动且较危险的,直接将电源线裸露在外,碰上上面所描述的暴雨那就是妥妥的漏电跳闸。PCB布线方面也相对随意,电源地和数字地没有进行隔离,容易串入干扰,在某些情况下会出现误动作。另外2018年联通就已经发布公告准备清退2G网络后续移动和电信也相继发出相同信号,也就是说这批控制板在未来会面临信号逐渐变差直到无法联网的问题,这是一个比较急待解决的问题,固件方面的主要缺陷还是在发生临时断电然后来电的情况时控制板无法主动恢复使用状态,需要用户主动自己重新开启。



电插锁也是12V直流电源输入,由控制板控制它的电源通断来驱动锁舌的伸出或回缩来实现锁定或解锁功能,但这种锁存在一些问题,特别在一些品控不佳的锁上尤为明显,在锁使用了较长时间后,锁舌磁化容易导致锁舌无力,自动回缩或伸出一半不动或不回缩甚至锁舌直接掉出,而且室外琴房经常面临潮湿环境,锁舌也出现锈蚀影响锁舌伸缩性能,并且锁工作时发热量高要求电流大,整体寿命偏低,孔位需要比较精准否则难以锁定,经常会有用户反馈门关不上或者门锁不住或者门锁不开均是因为这些问题导致。它的主要优点:锁上怎么用力也无法拉开,在玻璃门上也无效了,玻璃门使用这类锁需要一个门夹,虽然锁舌扛住了一切,门夹却没能扛住大力出奇迹。


插排这部分其实从考虑放在室外的时候就应该彻底摒弃了,也许是电工为了接线方便不愿意使用接线盒,在这样的恶劣环境下实在不适合使用插排作为接线手段,更不用说还混装过勒令停产的万用插孔插排,因此引发的跳闸也不在少数。


琴房在室外肯定避免不了闷热,所以配备了电梯空调,但正是因为这个空调导致前期投入了大量维护精力,其一是它在烈日炎炎下工作时制冷效果很差,特别是在安装了顶棚导致气流难以流通的琴房上制冷更是不尽人意,其二是它对通风管的保温有很高要求,如果保温棉没有把管道包装严实就会导致管道内凝结水珠通过出风口滴到用户头上,其三是它压缩机电路损坏率较高,也许是杂牌的原因又碰上频繁的开关,出现过有三台空调压缩机不能正常工作的问题,其四是外包公司并没有将控制板和空调协议进行对接,这导致除了开关空调没有其它功能,空调的功能控制只能通过对着天花板按遥控器控制,天花板上的对应位置装着一块空调自带的遥控板,每个用户对温度的敏感程度又不一样,公司不得不给每个琴房放置一个空调遥控器,这样就又冒出的新的问题,空调通电时是按照上次断电时的状态进行工作的,假设上个用户觉得冷极了用遥控把空调关了或者把温度调高,下个用户过来热极了由于上次断电时是关机状态那空调就不会通电启动或者保持着上个用户调的高温度,如果用户不懂得用遥控器自然就来投诉了,更奇葩的是有的遥控器干脆给小孩子偷走了,所以这一箩筐也是亟待解决的问题。

下图中是空调遥控板和电梯空调拆开的状态:


广告屏部分是由安卓盒子和带驱动板的32寸显示器组成,安卓盒子型号是MX3和MXQ似乎有区别,但都是低端盒子,主控是一颗晶晨S802,配备1GB运行内存和4GB存储空间,播放的广告内容都是通过读取插入的U盘文件,为此公司在某宝低价定制了一批刻有琴小站8GB存储空间的U盘,这样的U盘自然是存在问题的,文件传输速度极慢、容量虚标超出实际容量部分的数据会损坏或丢失、寿命短发热大,因此放在琴房里一起24小时工作后,经常会出现盒子因为无法正常读取U盘而播起了内部存储默认广告的情况。就像下面右边这样:

为什么要使用U盘而不把文件直接拷贝到内部存储播放呢?当我得知他们需要定期去手动更换U盘来更换播放的广告时我是震惊的,这里最核心的问题已经不是在于U盘是否好坏,而是这种手段存在问题,广告难道不应该是在线上推送线下自动更新吗?而且发现U盘里需要放置的文件也比较奇怪,上下的图片并不是分开播放的,只有视频是单独播放的,这就导致上图无法和下图分开播放,还会导致图片文件大小偏大,每个广告还得过一波PS,命名也有要求,如下图这样,这可好又多了一个需要解决的问题。

烈日的炙烤之下,不仅U盘会挂,连安卓盒子也挂了,经常会出现直接黑屏的情况,估计是因为只能采用5V供电,电压越低电流需求就越大,电流越大工作发热量就比较高,加上散热条件差就容易宕机,需要过去重启盒子才能恢复,于是就有了如下各种“自拍”了,在没有彻底解决前一些“惯犯”盒子的琴房先贴上了过胶的纸质二维码,这也是一大麻烦,当时听说这个盒子采购需要200多但实际在华强北逛的时候看到MXQ Pro这款的盒子也才百来块,又被坑一把唉。



显示器的问题在开始的一年还未显现出来,但一过保修期迅速进入报废期,开始出现多个显示屏损坏,一部分是被晒坏液晶,一部分是电源板损坏和电容鼓包滤波变差,电源板损坏的案例倒是大部分因为进了壁虎导致短路,一拆开就看到一只碳化的壁虎尸体,不过这类显示器毕竟不是户外专用屏,长期工作在恶劣环境下确实不易,何况价格就700一块,陆续因为屏幕无法正常显示换了一块又一块。


标注着“工业级”的4G路由器实属有点让人蚌埠住了,就像是试验机型一样,只提供一个LAN口和12V电源输入口,打开顶盖后除了主板部分就是两片贴片天线贴在外壳内侧,用料方面也很一般,实在远远低于工业级的标准,一个LAN口意味着就只能接个监控其它设备都只能通过Wifi连接,因这些不完善,监控网络连接问题将在此后很长一段时间里不断困扰着维护人员。


摄像头是和路由器、物联卡一起的外包方案,品牌是vsmahome,是一款云台摄像头,但塑料感十分重,提供以太网口和Wifi的两种接入网络方式,可以插TF卡本地存储录像,采用5V供电,只能通过支架简单固定在琴房顶上,最直接面临的就是物理和网络的不安全,物理方面这个云台可以用手把摄像头角度直接拨到其它位置,而且可以很容易将摄像头从支架上取下来,或者可以直接拔掉电源线,甚至可以把TF卡直接偷走就没录像存储了,网络方面经过我测试和大多数杂牌网络摄像头都一样存在可以直接通过RTSP协议默认账户和密码访问554端口直接获取监控画面,另外这个品牌没有提供云存储手段,因此本地无TF卡就无法回放过去的录像,查看监控需要下载他们官网提供的APP或者访问网页版,官网很难找并且也没有提供任何开放API,所以此产品基本不适用于共享琴房的场景,待解决问题再次+1。


这些就是我最初接手时整个项目的产品状态,接下来的所有关于这个项目的经历就是我改善这一切的过程记录。后续关于前中后期的描述均是以琴小站发展过程的时间为基准。

铺设琴房

在我正式入职之前,公司已经投放了三个琴房,接下来就是快速铺设琴房阶段,琴房正常收费是8元30分钟|12元45分钟|16元60分钟|24元90分钟,如果光靠练琴费用是不可能短期收回成本盈利的,公司前期主要战略是与机构和工作室合作,通过租赁共享琴房的方式为机构将教学场地分布式化,把琴房放在有生源的小区内,机构的老师去琴房上课,非上课时间其它用户过来练琴收取的费用也归给租赁方,琴房租赁费用大概是每年2W6。

理论上,假设琴房产品硬件和系统都很完善体验很好、公司有足够资源能够谈下物业铺设琴房、老师上课时间不会和用户时间产生太大的冲突,如果满足以上条件,这个走法是有较大盈利机会的,但现实是很骨感的,第一道坎就是琴房产品各方面状态还处于种子阶段,用户都表示体验差更不用提报名课程来学习的学生了,而且也没有为合作加盟专门定制系统,导致出现一种我租了但又没完全租的状态,第二道坎是公司的资源一直是不太充足的,琴房本身又是一个成本较高的设备加上物业费电费维护费是一大笔钱,对于一个创业公司前期不够省钱是致命的,第三道坎就是实际上老师和学生总会因为各种情况发生临时调课但用户却也是可以预约的,这就经常出现老师想调课时对应时间已经被其它练琴用户占掉的情况,这时候就又要费大量口舌跟用户解释和提供补偿,遇到强硬用户只能放弃调课,一来二去用户体验下降、老师学生体验全体下降。

基于上面这种情况,这套战略自然是以失败告终的,机构陆续都拒绝续约,幸运的是CEO很快意识到问题并调转船头让无机构运营空闲下来的琴房重新盈利,在此之前公司全员包括CEO都很辛苦不顾炎热风雨在线下安装和维护琴房,我也开始从办公室走出时常去现场维护和排查问题,依稀记得第一次爬到琴房顶上的那种慌张感,在无数次爬顶上后现在已经彻底习惯了在上面作业。


竞品分析

在整段经历中陆续发现了各种竞品,就先拿出来讲吧,比如雨果智慧琴吧、弹司令、巴巴杨共享琴房、微琴行、艺等仓、E家琴房、琴小练、天天共享钢琴、共享钢琴室等等一大筐,并且对这些竞品进行了基本的解析,最终确定三家在市场上存在竞争关系的产品,其实在这个比烂的行业里,后期产品优化好了这些威胁就不算事了。而且发现此类产品虽然很多,但生产厂家也就那三、四个,工厂基本坐落于东莞、惠州、广州。

三家竞品只有雨果智慧琴吧是在深圳本地运营的,也是公司最早盯上的竞争对手,他们的产品走的是和琴小站前期同样的战略,琴房整体成本可能达到琴小站的两倍,但他们的设备相对完善,门锁是无需联网的密码门锁,这种门锁内部和服务器采用了同一种算法,在一定时间内只会有一组有效密码,服务器提供该时段的密码即可在对应时间使用密码打开门锁,而无需联网控制,缺陷是不够便捷、成本偏高、时钟无自动校准、无法远程控制开门,优点是无需联网、无需携带手机。高配版外部有三面屏幕,利用率较低成本过高,内部空调功能相对完善但也只能在室内控制,放置了智能钢琴,用户端方面也采用微信小程序,整体效果很一般,琴房预约上可选时段很少且固定时长,收费也较高,当不同用户同时预约同个时段时会发生重单。他们的琴房铺设速度十分缓慢,从最开始到现在几乎没有新增琴房,网络方面由于他们的门锁不联网所以不存在离线可能。雨果还曾有内部人员想跳槽过来。


第二家是弹司令,坐标广州,也是早期发现的竞品,中间和公司打过一次外观专利官司,我们都持有外观专利但它比我们早两个月申请所以败诉了,因此我们不得不给所有第一二代琴房加装了黄色外框,弹司令琴房各方面硬件和琴小站都比较相似,他们几乎不把琴房放置于室外,这确实让维护省点心,但曝光率也降低了,他们前期也是同样的机构加盟战略,很快也遇到了瓶颈,中后期开始转向与各大音乐学院合作,将共享琴房放入学校中免费开放,用户端方面依然是微信小程序,整体效果很差,几乎没有用户体验,连基本的琴房图片都没拍标准,并且用户无法远程开门,必须要扫描琴房二维码才能开门,像大人给小孩开门的需求就无法满足,时段选择相对雨果多了一点但自由度还是很低,也存在重单问题。前期的铺设速度比较快,但很快就停了下来甚至不增反减,大量琴房开始离线,2021年的情况是35台琴房离线了19台,初步判断可能是2G网络无信号、停止维护或者断电。


第三家是巴巴杨共享琴房,坐标珠海,是中期突然出现的,他们主要战略是将琴房大量投放到各种商业区、广场、社区等人流量较大的区域,争取提高曝光量并依靠较高的练琴收费回收成本盈利,虽然也有尝试机构合作加盟和自营教师线下教学战略但似乎只持续了一小段时间,硬件方面就和其它产品大为不同,前后是两面落地玻璃,整个琴房变得十分通透加上整体浅色系配色增添了不少高级感(除了Logo实在太丑),但缺陷自然是隐私感不足,只有一面玻璃配备了窗帘,人流量大的区域新手完全不敢去练琴,简直大型社死现场,同时这个设计并没有考虑隔音效果,未贴吸音棉,这对于附近有住户的地方来说,免不了口诛笔伐,空调方面是最下血本的,采用的是格力的分体式空调(像我们美的分体空调都不敢买全新的,二手的都还嫌贵,没办法公司缺钱),内部放置了遥控器,用户端方面又又又是微信小程序,体验一样很差,水平基本处于雨果和弹司令之间,依然存在重单问题。琴房前期铺设速度也很快,但疫情之后就停止扩张了,2021年的情况是32台琴房离线了22台,离线的原因估计和弹司令比较接近。


这三家的情况分析下来,疫情过后基本都奄奄一息,都尝试过共享琴房的种种战略可能,每种战略都有成功的可能性,但在此之前是有诸多条件的,哪怕哪一环没走对都是致命的,资金不足、无自研能力、天不时地不利人不和等等都会随时卡脖子。琴小站有决胜希望的可能,但这是一个非常悠久的过程,我加入也许就是加快这个过程而已。

万金油

产品经理还在画原型图,设计师也还在设计新版小程序的页面,距离重构开始还有一段时间,这段时间里就不断的根据新增的需求更改老系统和页面以及修复现有的各种BUG。

比如发现经常有用户反馈支付了但订单没有生效,第一反应就是后台只做了支付回调处理但没有主动查单,当支付回调请求因为网络问题未能及时到达服务器或者处理失败,就会导致订单状态一直处于未支付状态,为解决这个问题用Node.js先写了个查单队列,确保订单状态能够及时更新。

或是发生了上面竞品分析所描述过的不同用户重单问题,两个用户都成功预订了同个时段,这时必然引发用户投诉,前期比较少发生是因为用户量少所以很难同时抢占同时段,为了解决这个问题就加入了应用锁,将预约请求串行化,并发时需要等待先入用户下完单,才能到自己,这时检查到已经存在该时段订单就返回已被预约。

顺便解决各种琴房硬件问题,比如各种设备的电源适配器应该用什么规格、控制板出现了奇怪的行为应该怎么判断和解决、门锁锁不上或者锁住不开该怎么解决、监控离线是什么情况、线路接完后无法开闸持续跳闸是什么原因等等,或者干脆去一趟现场调试,瞬间就兼职了电工,妥妥的万金油,哪里有问题放过去就能见效。

网络铺设

很快就迎来了2019年,这一年新年和往常一样,谁也还想不到会有一场新冠疫情席卷全球,年后回到公司时新办公区也开始装修,拉网络自然是少不了的,但老板说不想重新办宽带继续共用原来办公室的宽带省点费用,也就是说原来的光猫还不能迁过去,那这难度就很大了,新旧办公室相隔接近三十米,新办公区分为四个房间和一个中央办公区以及一个卫生间,四个房间分别是研发部、财务室、接待室、总裁室,办公室所有网线最后都集合捆扎到了接待室的窗边,于是我到五金店先买了三十五米的超五类网线,然后上京东买了几个五口百兆迷你交换机和一台TP的双频路由器、网线测试仪、一盒水晶头、压接钳,公司的宽带速率只有百兆对交换机就没有太高要求,准备搭条跨空大桥,先将网线两端按照T568B线序(橙白橙绿白蓝蓝白绿棕白棕,之前在工作室压接网线时背的顺口溜)压接,然后用测试仪确认压接正确,接着前往屋顶把网线一端下放到旧办公室窗口让同事接上旧路由器的LAN口,为了掌握主控权所以把这台旧路由的DHCP分配关掉变成一台交换机和AP,光猫的DHCP和拨号也是关闭的,准备由新办公区的路由器来负责分配和管理IP地址以及拨号,然后用绳子吊着网线另一端拉到新办公区的接待室窗口,让同事将网线插入到交换机上,并一一用标签纸标明每根网线对应的网口位置然后插入到交换机中,中央办公区只有两个网口,其中一个就接入的路由器的WAN口,并从LAN口扩展出了两条六米网线分别接到了两台交换机上,后面就只需要给各自的设备接入网线即可,但是至关重要的宽带账号和密码谁都不记得了,只知道肯定存在旧路由内,我从其它同事的电脑的浏览器密码记录中找到登入该路由器的管理密码,登录后通过备份路由器配置的功能得到了备份文件,成功从备份文件中获得了宽带账号和密码,接着让新路由器负责拨号,至此新旧办公区就完成联网了,直到很久以后宽带升级时才将光猫迁移过去新办公区。

装修完毕后我也搬过去那边,最开始时工位就在老板办公室旁边,下图是一年半后的样子,研发部的房间原本是公司副总的位置,后面由于公司市场部增员,外面中央办公区就全部给了市场部门,我和设计师就转进了研发部。


电磁锁

随着琴房的铺设数量增多,琴房使用的电插锁存在的问题也逐渐暴露了出来,出现开门时锁舌被卡住缩不回去要推拉一下才能开启或者锁舌未卡进门夹槽等问题,曾出现有用户被关在里面按开门开关虽然控制板有反应但锁舌无法被缩回,尝试了很多次才成功出来,为了解决这些问题我提出更换为电磁锁,电磁锁无需物理锁舌,仅依靠通电获得巨大的磁力,通过吸附安装在门上的铁板达到锁定目的。

最主要缺点自然是受到磁力量限制如果外部拉力超过负荷依然可以被开启,所以才会经常看见壮一点的小伙单手就能把使用电磁锁的门直接拉开,但这种情况一般是锁体本身可承受的力量太低,市面上可以看见常见的有180KG、280KG、380KG等规格的磁力锁,或是因为铁板未和磁力锁大面积接触,这样是无法获得锁标称规格吸力的,很容易被拉开,还有可能是磁力锁供电电压不足,也不排除真是大力出奇迹。磁力锁普遍都有一颗LED灯由于显示锁状态,比如红灯代表未吸合或未完全吸合铁板,绿灯代表完全吸合铁板获得标称吸力,不亮代表未通电解锁。

在大概估量后,决定全采购280KG吸力的带反馈的磁力锁,实测用双手是完全无法拉开门的,甚至用肩膀从内往外冲撞也是分文不动,就是怕钢化玻璃给撞碎了,这个规格的锁在之后的应用中均未出现可以被人为拉开的情况。由于是玻璃门所以还得买配套的玻璃门夹,这种门夹的长度一个顶电插锁门夹三个,所以稳固程度也进一步提升,磁力锁与电插锁一样断电后会自动解锁,虽然磁力锁会导致铁板短暂磁化导致还存在残余吸力,但铁板上存在一个小个圆形白色凸起物,里面是弹簧,确保在存在残余磁力时门依然可以很容易推拉开。

在确定磁力锁可代替电插锁后就要处理控制板上的接入问题了,发现两类锁体都采用同样的工作电压,那也就是可以通用了,门锁信号方面电插锁带反馈是四线的电磁锁带反馈是五线的,除了电源线正负极外,电插锁有常闭端和公共端两条线,电磁锁有常闭端、常开端、公共端三条线,也就是说需要门锁信号方面电磁锁只需要接四根线就可以了,不过可以确定的是这块控制板上并没有实现门锁信号上报,不明意义所在,但还是照样接上信号线吧,先在办公室先测试没问题就可以准备全面取代电插锁了。

临时方案

众所周知,广东只存在两个季节:夏季和秋季,随着年后气温迅速回升,空调无法调控的问题日益明显,放置遥控器的方案已不靠谱,决定将空调的遥控板从顶上拉到琴房内墙面固定,但也并非长久之计,因为这样依然无法在线上完成空调的调控,也无法确定空调是否已开启,房间室温也是无法在线上获知的,但还是暂时解决了燃眉之急,后面肯定还是重点解决的关键问题。

应急方案虽好但不是最好的,打补丁式的处理方法迟早会暴露弊端,不过现实总有一些特殊情况,比如固定屏幕的角铁用光了,工厂定制还需要一段时间才能到货,这时只要想解决大家还是会有各种办法的,比如找其它铁片作为固定支架↓。

或是在配送钢琴进不去电梯时,方法总比困难多:

日报生成器

老板要求大家特别是市场部每天要在群里发日报汇报一下今日工作情况,大家都照做了,但总会有打错时间、复制别人时忘改部分信息、排版错乱等问题,一天晚上闲来无事就在手机上写代码做了个日报生成器,无需填写时间和相关词汇自动生成,支持换行自动排序号、自动保存上次填写内容等,使用这个工具可以确保发出标准的日报,做好后放到了服务器上并提供了对应链接的二维码发到了公司群里。

新外观

我们都明白,现有的琴房外观与其它竞品或K歌房过于相似,放在公共场所不够吸引人,加上与弹司令打外观专利官司等综合原因之下我们很早就开始着手重新设计琴房外观,在兼具美观的同时还要尽量压低成本,最初还没有一个特定的方向,最搞笑的莫过于工厂做出了一个像保安亭的样品,当场把我们一众人丑到了。

不过很快设计师就找到了些许灵感,出了几个效果图,经过大家筛选确定下来外观造型,但建模和实际生产是有很大区别的,某些造型是工厂的折弯机做不出来或是对工艺有较高要求的,比如圆弧框架、圆弧玻璃,这些如果实现将会导致成本(如开模费用)大幅提高,因此最终生产稿还是做了很多权衡调整的,比如圆弧部位改为折角,不过从出效果图到实际投产中间隔了很长一段时间,因为一个产品当然不能止有空壳,旧琴房的那套设备很明显已经不能直接照搬过来使用,在无借鉴方案的情况下需要重新规划整个琴房产品,这就是后话了。

服务器磁盘扩容

在周日的清晨,刚醒来刷完牙洗完脸,就看见公司群里有人在问怎么C端小程序进不去了,我先是脑袋一懵,把所有导致服务宕机的的可能都过了一遍,同时赶紧把笔记本电脑拿了出来,在电脑上打开了MobaXterm开始登录服务器查看情况,起初我没有察觉到任何问题,看了下服务进程都有在运行,然后去看了一眼日志,惊奇的发现日志文件已经把50GB的系统磁盘挤满了,旧系统光日志文件就积累了二十多GB,赶紧将日志文件清除并将PHP-FPM重启一遍后终于是恢复了正常,尽管写工具定期清理日志文件,但长期以往也不是办法,增加数据盘成本也是比较高的,所以决定先扩容系统盘。

本来以为在控制台对系统盘进行扩容是立即就能生效的,结果扩容30GB后发现磁盘实际容量并没有扩容成功,重启也是无效的,过了一会想明白控制台操作的扩容只是扩大磁盘容量,但文件系统还未完成扩容,这让我联想起在重装Windows系统时对磁盘进行分区管理与这个也是同个原理。

通过 fdisk -l 命令可以看到系统盘 /dev/vda 确实是扩容了,根据阿里云的文档文件系统扩容需要先卸载主分区,但很明显这上面跑着一堆服务自然是没法直接卸除的而且当时不知道 /dev/mapper/vgxxx 分区逻辑卷以为跟 /dev/vda1 这类一样,各种卸载无效。

[root@host ~]# umount /dev/mapper/vgxxx
umount: /dev/mapper/vgxxx: device is busy.
(In some cases useful info about processes that use
the device is found by lsof(8) or fuser(1))

然后仔细去了解了 /dev/mapper 和常见的 /dev/vda 这类文件系统的区别,才知道数据盘是使用LVM,接着就开始研究LVM扩容并在服务器安装LVM工具

首先在系统盘 /dev/vda 上创建一个新分区,由于已经存在vda1所以新建分区号应该为2,执行 fdisk /dev/vda 并依次执行:

[root@host ~]# fdisk /dev/vdb
Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (2-4, default 2): 2,
First sector (104857600-167772159, default 104857600):
Using default value 104857600
Last sector, +sectors or +size{K,M,G} (104857600-167772159, default 167772159):
Using default value 167772159
Partition 2 of type Linux and of size 30 GiB is set

Command (m for help): t
Partition number (1,2, default 2):
Hex code (type L to list all codes): 8e
Changed type of partition 'Linux' to 'Linux LVM'

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.

这里报了一个设备繁忙的WANING,使用 partprobe 重读分区表即可(partprobe可以修改kernel中分区表,使kernel重新读取分区表。 因此,使用该命令就可以创建分区并且在不重新启动机器的情况下系统能够识别这些分区),接着只需要使用 mkfs -t ext3 /dev/vda2 格式化新建的分区 /dev/vda2 ,不过这只是创建了一个新增容量的分区,还没有完成原分区的扩容。

使用 pvcreate 命令创建PV并使用 vgextend 命令扩容VG vgxxx,接着可以使用 lvdisplay 查看已存在的LV信息获得LV Name,之后就可以用 lvextend 将100%的空闲空间全部用于扩容。

[root@host ~]# pvcreate /dev/vda2
WARNING: ext3 signature detected on /dev/vda2 at offset 1080. Wipe it? [y/n]: y
  Wiping ext3 signature on /dev/vda2.
  Physical volume "/dev/vda2" successfully created.
[root@host ~]# vgextend vgxxx /dev/vda2
  Volume group "vgxxx" successfully extended
[root@host ~]# lvdisplay
  --- Logical volume ---
  LV Path                /dev/vgxxx/lvxxx
  LV Name                lvxxx
  VG Name                vgxxx
  LV UUID                o2lYBF-7Txu-SVBv-SXyg-wZ5F-ivcf-RdqIf5
  LV Write Access        read/write
  LV Creation host, time izwz9h0tj0z3gn0gfuxxb1z, 2018-09-19 18:07:49 +0800
  LV Status              available
  # open                 1
  LV Size                <50.00 GiB
  Current LE             12799
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     8192
  Block device           252:0
[root@host ~]# lvextend -l +100%FREE /dev/mapper/vgxxx-lvxxx
  Size of logical volume vgxxx/lvxxx changed from <50.00 GiB (12799 extents) to 79.99 GiB (20478 extents).
  Logical volume vgxxx/lvxxx successfully resized.

最后一步再使用 resize2fs 重设文件系统大小即可完成LVM扩容,通过 df -h 也可以看到已经扩容成功了。

[root@host ~]# resize2fs /dev/mapper/vgxxx-lvxxx
resize2fs 1.42.9 (28-Dec-2013)
Filesystem at /dev/mapper/vgxxx-lvxxx is mounted on /home; on-line resizing required
old_desc_blocks = 7, new_desc_blocks = 10
The filesystem on /dev/mapper/vgxxx-lvxxx is now 20969472 blocks long.
[root@host ~]# df -h /dev/mapper/vgxxx-lvxxx
Filesystem                     Size  Used Avail Use% Mounted on
/dev/mapper/vgxxx-lvxxx   79G   11G   65G  15% /home

现在想起来整个过程也还是有点胆战心惊,生怕因为操作失误导致宕机,这也深度的反映了许多后端都说自己会运维,但实际运维需要面临的事情和压力比他们想象中的要多得多,也算给我上了一堂课。

手机就是电脑

很久以来,手机在我这的角色一直都不只是一台手机,它在需要的时候完全可以像电脑那样参与办公,当我不在电脑前的时候,一旦有什么需要处理的事情,我都会用手机通过远程桌面连接到公司电脑或通过JuiceSSH工具登录服务器,绝大部分小问题都可以通过这种方式获得解决,或者刚上线一个功能后就下班了,在公交车上时就会习惯的登上服务器看实时日志,一旦发现不对劲的地方赶紧在线vim改完,这样虽然很随意但只有我一个人实在没有测试和上线流程,还可以通过RemoteADB工具进入同内网开放5555端口的安卓设备运行命令等等,在我离职以前,带着手机一直是24小时oncall状态,群里和私聊消息也是第一时间处理,正常情况下,接听和回复最长不会超过6秒,如果遇上项目线上的紧急问题,没有电脑时手机就是第一战场。

重构产品

在开会确定下产品原型后就开始重构了,产品共经历了两次大重构,这是首次,本次重构主要目标是重构C端小程序、重构后端API服务并接入现有硬件云,所谓重构是彻底从零开始开发,并且不能干扰现有业务,也就意味着先要分批迭代上线是不允许的,必须一次成型且不能存在重大BUG,同时还涉及旧数据迁移与接入,目前为止依然是独自一人,未招聘其它开发,因此进度是比较缓慢的,不过经常忙着就有其它事需要我去帮忙处理,等回到工位又需要时间回到状态,中间催得也比较急,为了赶工期经常熬夜或者干脆通宵,早上再晚些去公司,黑眼圈日益严重,女友已经想掐死老板,甚至过来公司谈业务的客户看到我的黑眼圈都在向老板提出担忧,本次重构工期大概持续接近3个月。

好在努力并没有白费,6月份上线时各项数据相比之前翻了两倍,用户体验有所提升。


C端小程序方面根据原型和设计图并且结合自己总结的体验优化进行原生开发,在小程序这种两天一小改三天一大改的环境下,使用框架反而是一种阻碍,凭借着之前翻得烂熟的小程序文档基本没有遇到难题,唯一花了些时间与心思的就是自由的时段选择机制,后台可以以M分钟为步进生成N个T时长时段,比如以5分钟为步进以当前时间为基准生成今日0点之前的所有可用的30/45/60/90分钟时长时段,这将提供给用户最大的选择自由,比如它可以选择在12:05-12:35使用也可以选择在12:10-12:40使用而非单纯的以30分钟为步进,选择时如果当前选择时段与前后的部分时段重合也会将该部分时段置灰,支持现在使用和预约未来时间使用,现在使用将以当前时间推算,未来预约则是根据下个整5分钟时段推算,如果距离下个被预约时段还有充足时长依然需要提供选择,或者不足时长将会裁剪时长直到某个阈值但依然按照原时长收费,通过这些规则让时段选择相较竞品体验上升了一个档次。

另外印象比较深的是微信官方发布公告要求新上线小程序均不能打开小程序直接索取用户信息,而需要先让用户体验部分功能在需要时才索取,个人观点认为这对于用户体验无疑是一项巨大的提升,也在一定程度上减轻了小程序劣币驱逐良币的趋势,体验太差内容不是自己想要的干脆就不给授权,因此我将授权关口放置在了需要访问个人信息和琴房预约的位置。手机号绑定方面与之前有所不同,之前旧程序采用的是外包公司所使用的第三方短信平台,该平台短信服务质量堪忧,到达率低延迟久,导致错失了许多用户,刚好小程序开放了获取手机号码的API,用户可以直接授权手机号码或绑定新的手机号码,用户体验与成功率都提高了,运营还要求绑定时赠送100元余额促进绑定。发现大部分小程序开发者没有处理好二次进入的自动登录的问题,经常都是token失效后要求用户再次点击登录或是每次进入页面都先完成登录再继续提供服务,其实真正的自动登录应当做到用户无感知,我决定将自动登录融入到请求中,不是所有接口都需要鉴权的,而需要鉴权的接口在访问时如果服务器发现token失效则返回失效,这时小程序端应当采用Promise等待自动登录完成后无感知的自动重试登录之前的请求,在用户角度看来,就只是这项操作稍微慢了一点而已,并不会意识到刚刚发生了一次登录行为。

后端方面小程序API和后台系统几乎是耦合在一起的,存在许多共用接口,小程序中与硬件相关交互更是绕过主系统直接调用机器云,我打算将两部分小程序与后台业务分离开来,先采用Node.js基于Koa2开发专用于RESTful API的框架,采用路由件、处理件、数据件三层分离的方式处理接口数据,路由件负责过滤、校验、预处理请求参数并调用处理件方法和返回响应,处理件负责对数据进行相应处理并调用数据件进行具体数据操作和返回结果,数据件负责进行数据在Redis和MySQL间的CURD,由于当时时间关系并没来得及封装数据实体对象,所以数据件比较简易,并且给小程序端和接口都套上之前所说的RSA+AES混合加密,实际上这给调试带来了不少麻烦,其实微信小程序强制使用HTTPS协议已经是相对安全的了,接着把鉴权机制做好,统一响应格式以及响应错误码和对应信息,再把业务接口陆续补充完整,将原子业务如支付与扣款做好锁和事务封装,对接原来的硬件云让小程序端所有的硬件操作都需要通过本服务处理,支付方面彻底解决重单、漏单的问题,整体模块设计方面均预留了充足的扩展余地以便应对经常变更的需求,老板很容易一拍脑袋就下决定,所以后路还是要留充足一点,并且实现了模块热更新,可以在不重启服务的情况下直接替换模块缓存,这样可以实现无感更新,pm2虽然提供了watch模式但会导致服务重启,虽然很快但还是存在无服务间隙。架构上就没啥好说了,用户量预计几年内都很难有较大增长加上节省成本,就在CentOS系统的服务器上大概搭了下环境,使用Nginx主要负责服务与SSL代理以及一般静态文件访问,连负载均衡都用不上,静态文件方面再结合上CDN和OSS可以彻底搞定,然后就是Redis负责缓存用户session和各种缓存数据、热点数据后期也用到发布订阅通道,自然也是用不上集群单机足矣,并且考虑到存取逻辑较为简单也很少涉及原子操作就没有用到lua脚本,持久层则继续采用MySQL。

不过遗憾的是,当时着急上线C端后台系统却已来不及重构,因为之前的后台系统与API服务是完全耦合的,重构后端就当于直接放弃原有后台系统,这直接导致的是我将在很长时间里负担起大量人工后台操作,比如订单取消退款、新增或修改琴房信息、查订单信息等等,浪费了许多时间。

自从碰了这个项目开始,时间戳就如鬼魅一般一直伴随在我左右,太多涉及时间戳的处理与判断的逻辑了,导致对于时间的敏感性大大提高,比如看到3600会自然想到60分钟,看到900会自然想到15分钟

一元弹琴

运营提出了新的需求想要实现一个“一元弹琴”的活动,可以只花1元就能预约琴房30分钟还允许叠加,并且这个活动只有在每天的某个时段内有效,而且工作日与双休日的限制时段也不同,活动未来还会随时停止,其实当时想着还不如出一个活动和卡券系统,这样以减免的方式会合适一点,但一想到后台系统还没重构就头大,干脆先在现有服务硬编码了,逻辑上没啥难度主要是这个活动实在太BUG了,可以叠加意味着花很低的价格就可以承包整个优惠时段,也由于缺乏一些指引,导致部分用户并不清楚规则,主要的规则描述也只是屏幕上的一元弹琴轮播图片,等用户们都搞明白也适应规则后活动戛然而止时引发了不少用户投诉。

智能钢琴

老板也许是看上了竞品雨果琴房里的智能钢琴,找到了研发这款钢琴外设的公司,并叫上我和何哥一起过去瞧瞧看看有什么可以学习借鉴的地方,其实在此之前已经有接触过与之相似做钢琴外设和配套软件的公司,但他们提供的外设比较落后,那是一根黑色带有一排凸起的长条状物体,每个凸起物是对应钢琴弦槌的红外测距器,整根可以卡在钢琴顶盖内击弦机上方的位置,在弹琴击弦时弦槌会移动到对应位置的红外测距器前,这时就可以捕捉到按键信号,不过这还得配合上驱动和软件,配套软件是偏卡通化的,对方提供的软件是只能在iOS系统运行的,因此如果采用那设备成本肯定不低,于是谢绝了,而且红外测距的方式其实存在比较大的问题,比如灵敏度不高、无法判断击键的力度,就算采用它这套外设,我们还得做驱动移植和配套软件开发,种种难度之下就放弃与他们的合作了。

这次过来看的这款智能钢琴的外设就要好很多,采用的是键盘下光电传感器,这种方式不仅可以获知琴键是否被按下也能够推算出按键力度,但缺点是需要对钢琴进行改装,除去传感器还有一项外设是一条屏幕,之所以称作一条是因为它是一个横跨所有琴键条形屏安装在原本应是琴盖的位置,稍微试了下配套软件,可以确定是一台运行Android系统的设备,将配套软件作为桌面程序直接开机启动了,包含了几个钢琴游戏、曲库、曲谱库等,功能比较简单界面简约,适合的年龄层范围更大,目前一切还算比较美好,但是价格确实难以接受,这套外设和配套软件一起需要两万多,并且还得考虑安装和对接自家程序问题,价格都要达到一个琴房的成本了,在初步商量后决定放弃,老板还在考虑自研,我当时在想这自研个锤子,步子跨大了会扯裤裆的,当即表示如果要做必须还得招聘个嵌入式Android开发,工资还不能低。

产品离职

产品经理何哥由于一些原因被老板开源节流了,据老板说产品的工资达到我的两倍以上,我不知道是否是因为老板在找我谈到何哥时我对他的目前工作状况描述得不够好,在谈话之前何哥也似乎与老板在总裁室里吵过一次架,最后他还是离开了公司,在公司没有及时发下工资知道我生活困难时他给我转过500,虽然工资发下来后马上还回去了,但还是很感谢他,后面还多少有点联系,结婚时还邀请了公司的老成员包括老板去参加婚礼,只是产品走了老板一拍脑袋的主意多半要直接砸到我和设计师头上了,毕竟许多想法主意是需要技术论证的,还要考虑成本可行性等等,老板是不愿意听见不行二字的,虽然对于我老板不会大声苛责,但也往往都是能实现的尽量实现难以实现的会折中委婉处理并告知可能面临的问题和风险,产品在许多时候不是给程序员添乱,也许是一堵防火墙,用于隔离开天马行空和不切实际的想法,尽量提供可行的方案。

重构广告机

线下琴房开始出现越来越多因U盘过热无法读取、安卓盒子过热宕机导致的屏幕广告无法显示黑屏的问题,并且随着各种运营活动的上下线,对于广告机所播放广告的时效性有了更高的要求,琴房也比只多不少,分布地区更是好几个,让人跑去换U盘已经不实际了,急需一个可以在线上发布广告的广告机,在这样的背景下,虽然我已经很早就要求招聘Android嵌入式开发,但给的薪资实属寒碜:5-8K,好不容易有过来面试的结果还都是培训机构出来的,应届生经验也是完全不足,一狠心算了,我自己做,智能钢琴我是没精力做,但是这么个广告程序还是没问题的。

脑子里开始回想起以前写Android的记忆,不过Eclipse+ADT插件的时代已经彻底过去,Android Studio这款IDE才是主流,所以马上就开始下载IDE并安装SDK和相关组件以及镜像,就这样在几乎没有经验的情况下开始了广告机的开发,Android Studio当时已经支持使用Kotlin语言,虽然彼时Google还没有将Kotlin推举为Android开发官方语言,但也是风头正盛的状态,对于Kotlin我不能说不太了解,只能说是一无所知,为了保险我还是先选择了Java,直到后期广告机二次重构时才选择了Kotlin,使用Android Studio开发的感觉是Eclipse所达不到的,丰富而准确的语法提示,代码补全也相对更好,在调试方面更加方便。

想着公司现在搬来的这台机子性能有限,内存还给核显吃掉1GB,怕跑不动,之前那台惨遭嫌弃的游戏本正放在出租屋里用,游戏本配置还是很可以的,所以跟老板申请一周不来公司在家办公完成广告机程序顺便还能省下来回公司的时间,老板同意了。

这一周自然也是完全没偷懒,旧广告机程序源码是没有的,但该程序确实十分粗糙,它只读取包含上下轮播图拼合的图片和中间的视频文件,我决定将广告播放的资源切为顶中底三类,分为顶部轮播图、中部轮播视频、底部轮播图,这样播放上下轮播的逻辑就可以完全错开了,上部轮播图往往都比下部轮播图多,所以分离很有必要,除此之外二维码也是单独分离显示的,这样就不用为了不同琴房制作不同的底部轮播图,大大降低人工成本,接下来的挑战就是与服务器的连接,采用的是主动注册的方式,广告程序首次启动时会等待联网,联网后会向服务器发起注册请求,服务器允许注册后程序将进入轮询广告数据状态,当服务器存在与它绑定的广告数据时它就会解析数据并下载对应资源到存储目录中,存储完成后将自动开始播放,顶部和底部轮播图的切换间隔是由广告数据决定的,视频则是播放完毕时自动切换到下一个,另外还会定时向服务器发送心跳请求和获取新广告请求,心跳用于保活让服务器知道广告机是否在线,当存在新广告时广告机会下载新的广告文件并存储与当前广告ID的目录中不会与旧广告文件发生冲突,下载完毕后程序则切换到最新广告播放,旧的广告数据将被移除,其中比较核心的是耗时处理不能放在UI线程需要另起线程或使用协程,否则会导致画面渲染卡顿甚至ANR,很快就完成了开发工作,但在测试时发现运行了几个小时后崩溃挂掉了,使用Profiler检查后发现是一个请求对象没有释放导致内存泄露,修复后就解决了。刚好手上还有一台山寨平板,虽然屏幕有点短,拿来测试还是不错的,打开USB调试连上了它,在经过模拟器+实机连续一天半的测试后确认没有出现问题。

第二天就拿着成品前往公司测试打包,命名为琴小站广告组件,至此终于摆脱了以往线下广告更换难、广告图制作麻烦、广告机在线状态未知等问题,并且开始给安卓盒子安装替换原有广告程序,同时为了监控播放状态还安装了TeamViewer,针对安装流程顺便做了个CLI。

但正如上面所说实际上这是第一次重构广告机,意味着后续还出现了一些问题,我自知这次开发得过于赶进度了,仅花了三天半,有很多优化点没有做,比如安全性是比较低的,连请求防篡改的机制也没有,并且使用了实时性比较差的轮询请求,按理应该使用WebSocket或TCP等其它实时传输连接协议,并且注册机制是比较简陋的,暂时也没有后台系统可以用于广告机的管理和上传广告文件,还有一项很重要的文件有效性和格式校验没有做,以及轮播图的切换部分没有开协程处理,在切换大图时会对UI线程造成短暂阻塞,看上去就是视频卡了几十ms。

这些问题附带着比之前更多的问题压到我身上,比如在我重构出后台系统之前所有的广告机信息都需要手动管理,广告的图片或视频也还得我手动上传和检验,给到我的图片经常会出现过大或尺寸不符,视频也是经常过大,这时如果设计师忙我就得自己压缩一遍,通过网络下载广告文件到广告机意味着对琴房的路由器网络有较高要求,如果文件资源过大,下载耗时就会更长,偏偏许多琴房的所用的“工业级”路由器网络性能并不佳或是碰上财务没有及时给流量卡续费的情况就加剧了这种情况,在没有写自己用的自动化上传工具之前,文件上传下载无校验这块吃了亏,因为失误错把图片链接作为视频链接一起推送给了广告机,广告机也不校验文件类型直接下载并且播放,自然是无法正常播放的,或是链接缺失一部分被推送过去,直接返回下载更新失败,但却不知道是哪个文件有问题,这就是缺失管理系统和终端验证的巨大危害,后面还出现了更奇葩的问题,我们发现部分广告机在长时间运行后会出现中间视频不播放的情况,表现为中间黑屏但其它的正常播放,视频采用的是VideoView组件,在办公室不论如何测试都无法复现,仅在线下琴房一段时间后突然发生,未检测到内存泄露,猜测可能是VideoView因为某些原因被回收掉了,寻找了许多资料都未能确定具体原因,幸好之前安装了TeamViewer可以远程重启广告程序恢复,不过在第二次重构时实现继承TextureView的VideoTextureView解决了该问题,这所有的经历持续了很长一段时间,像一场悠长的噩梦。

监控直播接入

之前所说的网络摄像头麻烦也不少,总有人去拨弄云台,导致拍摄方向不正确,更有甚者把内存卡或者摄像头都给拿走了,加上没有云存储,导致需要查看时往往都没法获得关键信息,属于防君子不防小人,而且没有提供开放平台,这样的话我们无法将监控直播接入到自己的平台,所有人还得另外下APP,安装时也没有插网线只连Wifi,导致传输有些不稳定。

起初是希望在不替换现有摄像头方案的情况下给摄像头价格半球型罩子,就像大家在电梯或地铁里常见的那种监控遮罩一样,主要目的就是防止直接接触摄像头,于是和设计师前往了华强北,搜寻各种摄像头遮罩,也不是没有,但是很少,就算有但也很小,不大可能遮住这么大个摄像头云台,就算把摄像头半截身子塞到天花顶上,也是很难实现的。

RK3288主板

采购了一批RK3288的安卓主板,这是用于替换原本的安卓盒子,不过如果只是为了播放广告是无需使用这个相对高配主板的,主要是为未来实现上面提到过的“天马行空”方案做了预备,毕竟要同时带起条形屏+广告屏还要负担一些软件运行对硬件是一次不小的考验,


更多回忆还在撰写中,敬请期待…

B端小程序

电工

续费风波

重点区域

疯狂跳闸

路由器

进军海南

觅跑改琴房

停卡风波

地图爬取

动态抠绿幕

疫情来临

空调导风

误打误撞PLC

STM32

控制板初代机

逻辑分析仪

空调遥控

NB网络

4G Cat.1

设计控制板

焊接控制板

编写控制板固件

调试控制板固件

开门续期
断网重连
红外编码定义
下载器

硬件云服务开发

控制板配置工具

激光钢网

线路腐蚀

广播报道

报纸报道

用户自媒体

二次重构广告机

广告云服务开发

广告机管理与发布

死心

工厂实装

二次重构产品

心历程

薅ASML光刻羊毛

时间旅行者

快应用漏洞

思想

脏数据检查

新世界游戏开发

NFC名片

86智慧面板

模拟PID算法

入职思迪

视频渲染引擎开发

聚合服务开发

虚拟人引擎开发

升级部门技术总监

基于无头浏览器实现视频渲染引擎

自动化视频量产平台搭建

AIGC平台搭建

LLM大模型微调训练

LLM大模型的应用

上央视了

离职休息

失业半年

找到工作

挖到智谱清言漏洞

积极参与GLM社区

LLM Red Team成立

kimi-free-api开发

emohaa-free-api开发

glm-free-api开发

qwen-free-api开发

step-free-api开发

表情包智能体实现

展望工作流Agent能力

如转载本文章必需注明来源地址.

#回忆录