树莓派上的系统自动更新

树莓派上的系统自动更新


有这样一个问题,假如我们有成千上万台设备在运行,假如系统出了BUG,或者我们需要添加什么功能,我们不可能派人每一台每一台的去修复吧。因此我们需要做一个自动更新的东西,假如系统出现bug,或者需要增加新功能,我们就像是在修改网站一样,只需要在网站上修改代码,然后大家所有的设备上都更新了。

我们需要怎么做呢,首先我们需要在数据库上建立一个表,至少要两个字段,当前版本号和当前要更新的文件的下载地址,当然我们的更新文件是以zip的方式打包的。

像下面这样:

<code>DROP TABLE IF EXISTS `yzn_versionctl`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `yzn_versionctl` (
`versionid` int(11) NOT NULL DEFAULT '0',
`version_url` varchar(245) COLLATE utf8_bin DEFAULT '',
PRIMARY KEY (`versionid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
/*!40101 SET character_set_client = @saved_cs_client */;/<code>
<code>--
-- Dumping data for table `yzn_versionctl`
--
LOCK TABLES `yzn_versionctl` WRITE;
/*!40000 ALTER TABLE `yzn_versionctl` DISABLE KEYS */;
INSERT INTO `yzn_versionctl` VALUES (2,'http://cms.o4.com/update/raspberrypi_client.zip');
/*!40000 ALTER TABLE `yzn_versionctl` ENABLE KEYS */;
UNLOCK TABLES;/<code>

我们通过php后台,下次要更新系统时,只需要通过后台提高系统版本号,并且上传相应的更新文件就可以了。

然后树莓派就需要通过php获取到这些版本信息,我们看看php后台代码是怎样的:

<code>    public function getVersionUpdateInfo()
{
$versiondata = $this->Member_Model->member_getVersionUpdateInfo();
return json_encode($versiondata[0]);
}/<code>

查询数据库:

<code>    public function member_getVersionUpdateInfo()
{
$data = Db::name('versionctl')
->select();
return $data;
}/<code>

解决跨域问题:

<code>Route::get('getVersionUpdateInfo','api/mobile/getVersionUpdateInfo')->allowCrossDomain();/<code>

好,到这里,我们就可以通过下面这种方式去获取版本信息了:

<code>http://cms.o4.com/getVersionUpdateInfo/<code>

接下来,我们看看树莓派上的nodejs如何操作,要进行更新,我们需要安装下面的东西:

<code>sudo npm install pm2 -g       -- 用于启动和管理nodejs进程
sudo npm install fs -- 本地文件操作
sudo npm install axios -- 用于和php后台交互
sudo npm install unzip -- 用于解压文件

sudo npm install node-schedule -- 用于定时任务,半夜三更才更新系统/<code>

然后,我们接下来看看具体操作步骤,首先是要从网站上下载文件,代码如下:

<code>const http = require('http');
const fs = require('fs');
function downloadFileAsync(uri, dest){
return new Promise((resolve, reject)=>{
// 确保dest路径存在
const file = fs.createWriteStream(dest);
http.get(uri, (res)=>{
if(res.statusCode !== 200){
reject(res.statusCode);
return;
}
res.on('end', ()=>{
console.log('download end');
});
// 进度、超时等
file.on('finish', ()=>{
console.log('finish write file')
file.close(resolve);
}).on('error', (err)=>{
fs.unlink(dest);
reject(err.message);
})
res.pipe(file);
});
});
}/<code>

然后是解压文件:

<code>function unzipFile(ExtractPath,zipFile) {
\treturn new Promise((resolve, reject) => {
\t\t\tfs.createReadStream(zipFile).pipe(unzip.Extract({ path:ExtractPath}).on("close",() => {
\t\t\t\tconsole.log('unzip success');
\t\t\t\tresolve("unzipSync Done")
\t\t\t}).on('error',(err) => {
\t\t\t\treject(err)
\t\t\t}))
\t\t\t.on('error', (err) => {
\t\t\t\treject(err)

\t\t\t})
\t\t})
}/<code>

首先,我们在我们系统中保存一个版本号,每次系统启动后就先对比php后台上的版本号,如果发现对不上,就从网站上下载最新的系统文件,然后解压更新本地机器上的文件,本地系统更新完成后,重启整个系统。

下面是系统更新的代码:

<code>function VersionUpdate(curVersion) {
\taxios.get(update_url).then(async(res) => {
\t\tconsole.log('curVersion:'+curVersion+' newVersion:'+res.data.versionid+' updateUrl:'+res.data.version_url);
\t\tif(res.data.versionid != curVersion) {
\t\t\tawait downloadFileAsync(res.data.version_url,'raspberrypi_version.zip');
\t\t\tawait unzipFile('./','raspberrypi_version.zip');
\t\t\tconsole.log('update success.last version:'+res.data.versionid);
\t\t}
\t\telse {
\t\t\tconsole.log('not update.curVersion:'+curVersion);\t
\t\t}
\t}).catch(function (error) {
\t\tconsole.log('version update error:'+error);
\t});\t
}/<code>

而系统重启就要交给pm2这个工具了,它有一个功能就是检测到当前代码出现变动就自动重新启动系统。

<code>pm2 start ./bin/www --watch
--watch参数,意味着当你的express应用代码发生变化时,pm2会帮你重启服务/<code>

我们有两个地方要更新,一个是在每次系统启动后就自动更新到最新的系统,另外就是每晚夜深人静的时候的时候检测系统是否更新,因此我们需要用定时任务。

关于node-schedule的用法可以参考下面的参考文档,我们这里代码如下:

<code>const  scheduleCronstyle = ()=>{
//每天的凌晨1点1分30秒触发
schedule.scheduleJob('30 1 1 * * *',()=>{
VersionUpdate(curVersion);
});
}
scheduleCronstyle();/<code>

OK,到这里,我们整个系统就可以如做网站般简单了。你只需要后台操作一下,就可以更新所有的设备,可以安心去睡个好觉了。


参考文档:

pm2常用的命令用法介绍

https://blog.csdn.net/chengxuyuanyonghu/article/details/74910875

Nodejs定时任务(node-schedule)

https://www.jianshu.com/p/8d303ff8fdeb

鼹鼠智能售货机系统(Mole intelligent vending machine system)

https://gitee.com/akinggw/MIVMS


分享到:


相關文章: