基于MQTT协议的物联网云平台开发记录
记录一下科创开发
把过程中碰到的主要问题都在这里记录
用到的工具:Xshell7, Xftp7
IP: 39.103.142.138
阿里云:
提跃宇
Tee964708596.
docker容器启动失败
在进行硬件数据上云过程中,需要用到broker,但是服务器里部署的emqx无法正常启动
没办法,完全从零开始玩docker,碰到的问题目前都无法靠自己解决
记录一下常用指令
1 | docker ps -a |
MQTT协议中间用到的Broker: emqx无法正常启动,一启动就掉,看status为1秒前退出

查看log

去emqx github issues找到了类似问题vm.args needs to have a -name parameter.,貌似是说磁盘空间占满了
查看磁盘占用情况:

试着进入对应目录删除log文件,但是还是没什么效果
去咸鱼解决问题,花30块找了个老哥也没解决问题,找出问题就没下文了

咸鱼老哥说安装的镜像太多,导致磁盘占用高
但是我看阿里云服务器是120G的磁盘,不应该占满啊
因为服务器到期原因,被迫重启
安装所需依赖
总共是3个文件夹:
rain-cloud-vue
:前端项目
rain-iot-device
:虚拟设备
rain-iot-server
:后端项目
首先该做的事就是,进入每个文件夹下,运行npm install
指令,安装所需依赖
package.json
文件是一个Node.js项目的核心文件,它包含了项目的元数据和依赖列表。你可以通过运行以下命令来安装package.json
文件中列出的所有依赖:
1 >npm install这个命令会读取
package.json
文件,然后下载并安装所有列出的依赖到node_modules
目录。如果你的项目中已经有一个package-lock.json
文件,那么npm install
命令会根据这个文件来安装依赖,以确保你安装的依赖版本和其他开发者安装的版本一致。在你安装依赖之后,你应该就可以正常运行你的项目了。
本地启动项目
因为之前没有用过JavaScript,nodejs这些东西,所以绝大部分工作是问的bing
首先得本地启动现有的项目,步骤如下:
首先在rain-iot-server
路径下输入npm start
,这样可以启动服务器
因为在package.json
文件中有一个 scripts
部分,并且在这个部分中有一个 start
命令,所以需要通过在命令行中输入 npm start
来启动项目
然后再在rain-cloud-vue
路径下输入npm run serve
,这样就可以正常打开前端
因为在package.json
文件中有一个 scripts
部分,并且在这个部分中有一个 serve
命令,所以需要通过在命令行中输入 npm run serve
来启动项目
能在后端的控制台看到全部的HTTP请求
我记得后端控制台输出需要调用console.log
函数,为什么我没在get
函数里看到对应的函数,却仍能在控制台看到对应的GET请求?
这是因为Express.js框架自动记录了所有的HTTP请求。在你的代码中,你使用了
morgan
中间件,这是一个HTTP请求记录器中间件。当你调用app.use(logger('dev'))
时,你其实是在告诉Express.js使用morgan
来记录所有的HTTP请求。
morgan
会自动在控制台输出每个HTTP请求的信息,包括HTTP方法(如GET或POST)、请求的URL、HTTP状态码、响应时间等。所以,即使你没有在路由处理函数中调用console.log()
,你仍然可以在控制台看到对应的GET请求。
哈希路由
在分析代码时,我有点疑惑后端的GET方法:
1 | /** |
我访问的界面明明是
http://192.168.32.129:8080/#/product/productList,那为什么这里的get
函数参数是/
根路径?
你提到的
http://192.168.32.129:8080/#/product/productList
是一个使用了哈希路由(hash routing)的URL。哈希路由是一种在前端应用(如单页应用)中常见的路由策略。在这种策略中,URL的
#
后面的部分(如/product/productList
)会被前端应用用来决定要显示哪个页面或组件,而不是发送到后端服务器。因此,当你访问http://192.168.32.129:8080/#/product/productList
时,你的浏览器实际上发送的请求URL是http://192.168.32.129:8080/
。然后,前端应用会查看
#/product/productList
,并根据这个路径渲染对应的页面或组件。在你的例子中,这可能是产品列表页面。所以,当你点击“显示产品列表”的按钮时,前端应用可能会发送一个到
/api/v1/products
的GET请求来获取产品数据,这个请求会被后端的router.get("/")
路由处理。你需要查看前端的路由文件。在一个使用Vue.js的前端项目中,路由通常在
router.js
或者router/index.js
文件中定义。这个文件中会定义一个VueRouter
实例,其中包含了一个routes
数组。这个数组中的每个对象都代表一个路由,包括路径(path
)、组件(component
)等属性。例如,你可能会看到类似下面的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 >import Vue from 'vue'
>import Router from 'vue-router'
>import ProductList from '@/components/ProductList'
>Vue.use(Router)
>export default new Router({
routes: [
{
path: '/product/productList',
name: 'ProductList',
component: ProductList
},
// 其他路由...
]
>})在这个例子中,当用户访问
#/product/productList
时,前端应用会显示ProductList
组件。当你点击“显示产品列表”的按钮时,
ProductList
组件可能会发送一个GET请求到/api/v1/products
来获取产品数据。这个请求会被后端的router.get("/")
路由处理。
路由路径
我点击产品列表界面,前端给后端发送的HTTP请求是:
GET /api/v1/products?column=createTime&order=desc&field=id,productId,productName,activeStatus,description,createTime,updateTime&pageNo=1&pageSize=10
后端一开始的app.js
有如下定义:
1 | app.use('/api/v1', apiv1) |
这就设置了基础路径,于是所有以 /api/v1
开头的请求都会被路由到 apiv1
所以,当在 apiv1
中定义一个 router.get("/")
路由时,它实际上是处理 /api/v1
的 GET 请求
然后在routes/apiv1/index.js
中有如下定义:
1 | const router = require('express').Router() |
所有以 /products
开头的请求都会被路由到
productRouter
本地安装EMQX
我在虚拟机上安装了EMQX以后才能正常运行程序,这里是EMXQ的文档
运行以下命令启动 EMQX。
1 >./emqx/bin/emqx start现在您可通过浏览器访问 http://localhost:18083/(localhost 可替换为您的实际 IP 地址)以访问 EMQX Dashboard 管理控制台,进行设备连接与相关指标监控管理。
默认用户名及密码:
admin
public
目前已经改密码为
leizhibo1
运行以下命令停止 EMQX。
1 >./emqx/bin/emqx stop后续如需卸载 EMQX,您可直接删除 EMQX 目录即可完成卸载。
这个Dashboard就是可以监测EMQX状态的,端口是18083
虚拟机截图,可能有些不清楚

然后需要把rain-iot-device/sdk/iotDevice.js
里EMQX的端口重新设置为1883
而不是11883
,这里可能是学姐本人打错了:
1 | constructor({ serverAddress = "127.0.0.1:1883", productId, deviceId, secret, clientID, storePath } = {}) { |
EMQX 3.2.0
你说得对,但是版本安装错了,应该安装3.2.0
最新版已经不自带MongoDB的插件了
我在官网下载目录找到了这个版本,下载发现确实有了我要的插件,无敌了
但是我草你妈,这个版本的EMQX不能正常部署
查了一堆,终于在官方的一个问答中找到了建议:Windows建议用docker
你说得对,但是我现在要用docker了
虚拟机装docker装不上?我服了
这下得捯饬捯饬Linux虚拟机了,毕竟老师花了8000买了一年,我也有使用权限,狠狠造;但是不能像之前一个学长一样,部署东西把本来好好的项目整报废了,而且这个项目还是跟我这个逼科创相关的
Erlang runtime
这个我真的操你妈了,安装这玩意快给我整死了
./configure
提示缺东西:
1 | configure: WARNING: Can not find wx/stc/stc.h -g -Wall -O2 -fPIC -g -O2 -Wno-deprecated-declarations -fomit-frame-pointer -fno-strict-aliasing -D_GNU_SOURCE -D_THREAD_SAFE -D_REENTRANT -I/usr/lib64/wx/include/gtk3-unicode-3.0 -I/usr/include/wx-3.0 -D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXGTK__ -pthread |
然后我找到stc.h
这个文件了,在/usr/include/wx-3.0/wx/stc
目录下
我给他添加到环境变量以后还是找不到这个文件,搞了他妈的一下午一晚上,搞得我想杀人
终于,找到了类似问题:
Erlang Build Fails: Can not link the wx driver, wx will NOT be useable - Stack Overflow
结果竟然是他吗的没装C++?
I got the same error while building erlang on CentOS 7. I too was missing the C++ compiler. After doing yum install gcc-c++, I was able to build erlang successfully.
我真是你妈草了
运行yum install gcc-c++
就能成功安装C++
然后再运行./configure
就能解决了
还得是stackoverflow,毕竟你问bing的时候,bing不知道你装没装C++
修改记录
前端后端添加删除产品功能
单个删除按钮
我在前端的产品列表界面,即rain-cloud-vue/src/views/product/productList.vue
中:
修改了HTML文件,修改了handleDelete
函数代入的参数,使点击按钮绑定handleDelete
函数后正常工作:
1 | <el-button type="danger" size="mini" plain @click="handleDelete(scope.row.productId)">删除</el-button> |
修改了import文件,使deleteAction
被包括进来:
1 | import { getAction, postAction, deleteAction } from "@/api/axios"; |
修改了url
的定义,添加了delete
选项:
1 | url: { |
重写了删除函数handleDelete
:
1 | handleDelete(id) { |
我在后端的产品路由,即rain-iot-server/routes/apiv1/product.js
中:
添加了后端处理删除请求的功能:
1 | /** |
批量删除
修改了处理选中产品行的函数:
1 | handleSelectionChange(val) { |
重写了批量删除产品的函数:
1 | handleBatchDelete() { |
虚拟设备更新EMQX端口
需要把rain-iot-device/sdk/iotDevice.js
里EMQX的端口重新设置为1883
而不是11883
,这里可能是学姐本人打错了:
不过貌似不是打错了,因为后面很多次出现的端口都是11883
,我不清楚,因为我本地11883
出错了,而1883
是正常的
1 | constructor({ serverAddress = "127.0.0.1:1883", productId, deviceId, secret, clientID, storePath } = {}) { |
这样才能正常连接虚拟设备,并且可以在EMQX本地的dashboard中看到设备连接
前端正常显示设备的创建时间
在rain-cloud-vue/src/views/device/deviceDetail.vue
文件中,可以看到“创建时间”一栏是写死的“2022年3月27日17:33:31”,于是就希望显示真正的创建时间,做如下修改:
在rain-cloud-vue/src/views/device/deviceDetail.vue
文件中的computed
部分添加一个函数:
1 | formattedCreateTime() { |
这个函数用于将ISO格式的日期(2024-03-28T01:18:35.253Z
),转化为人更好阅读的2024-03-28T01:18:35.253Z
然后将这个返回的字符串显示在对应位置:
1 | <el-descriptions-item> |
用{{}}
包括起来是Vue里的一种用法:
在Vue.js中,
{{}}
被称为文本插值,它用于将数据绑定到视图。当你在{{}}
中写入一个变量名时,Vue.js会自动将这个变量的值插入到HTML中。
设备列表界面
前端设备总列表显示启用数字不正确
还能有这种问题?我是真不明白,你是怎么写错的,能不能对自己的毕设上点心?
rain-iot-server/controllers/deviceController.js
里的getAllDevices
函数修改:
1 | const getAllDevices = function (req, res) { |
前端设备列表启用设备数目即时刷新
在rain-cloud-vue/src/views/device/deviceList.vue
文件中,将handleEnable
函数修改为以下形式:
1 | /** |
批量删除功能重写
源代码写的有问题,做以下修改:
在rain-cloud-vue/src/views/device/deviceList.vue
文件中,将handleBatchDelete
函数修改为以下形式:
1 | handleBatchDelete() { |