This commit is contained in:
Iruka 2024-09-27 18:48:24 +08:00
parent e58cc90113
commit 0a9ec18bc0
3 changed files with 333 additions and 242 deletions

73
App.vue
View File

@ -7,11 +7,8 @@
data() { data() {
return { return {
indexData: new indexUtil(this.indexDataHandler), // indexData: new indexUtil(this.indexDataHandler), //
dc: new dc(), dc: new dc(), //
mqtt: new mqttUtil(), mqtt: new mqttUtil(this.mqttMsgHandler), //Mqtt
mqttObj: {
topics: []
},
} }
}, },
globalData: {}, globalData: {},
@ -22,8 +19,8 @@
// #endif // #endif
// mqtt // mqtt
uni.$on("mqtt-link", () => { uni.$on("mqtt-link", (userId) => {
this.mqttLink(); this.mqttLink(userId);
}); });
// mqtt // mqtt
uni.$on("mqtt-subscribes", topics => { uni.$on("mqtt-subscribes", topics => {
@ -56,56 +53,26 @@
this.dc.setValves(this.indexData.selectItem.id, this.indexData.device.waterOutlets); this.dc.setValves(this.indexData.selectItem.id, this.indexData.device.waterOutlets);
} }
uni.hideLoading(); uni.hideLoading();
// console.error("indexDataHandler_2:", { console.error("indexDataHandler_2:", {
// indexData: this.indexData, indexData: this.indexData,
// dc: this.dc, dc: this.dc,
// }) })
}, },
setTime: function() { //Mqtt
console.error(this.globalData.num); mqttLink(userId) {
// setTimeout(() => {
// this.globalData.num++
// console.error(this.globalData.num);
// this.setTime();
// }, 1000)
},
mqttLink() {
// wx.connectSocket promisify SocketTask
uni.connectSocket = (function(connectSocket) {
return function(options) {
console.log(options)
options.success = options.success || function() {}
return connectSocket.call(this, options)
}
})(uni.connectSocket)
console.error("mqttLink"); console.error("mqttLink");
// #ifdef H5 this.mqtt.link(userId);
this.mqtt.link();
this.mqtt.client.on("connect", error => {
console.log("连接成功")
console.error("client:", this.mqtt.client);
})
this.mqtt.client.on("error", error => {
console.log("连接异常")
})
this.mqtt.client.on("reconnect", error => {
console.log("重新连接")
})
this.mqtt.client.on("message", (topic, message) => {
console.log("接受消息")
console.log("message", message.toString())
this.mqttSendMsg(message);
})
// #endif
}, },
mqttSubscribes(topics) { //Mqtt
this.mqttObj.topics = topics; mqttEnd() {
console.error("mqttSubscribes:", topics); this.mqtt.over();
}, },
mqttSendMsg(msg) { //Mqtt
uni.$emit("mqtt-msg", msg); mqttMsgHandler(topic, data) {
console.error("mqttMsgHandler:", {
topic: topic,
data: data,
});
}, },
} }
} }

View File

@ -97,7 +97,9 @@
<text>基站</text> <text>基站</text>
</view> </view>
<view class="fixed" style="width:calc(100% - 30%); justify-content: flex-end;"> <view class="fixed" style="width:calc(100% - 30%); justify-content: flex-end;">
<view class="iconfont icon-xh icon"></view> <view class="iconfont icon-xh icon"
:class="[ mqtt.connected ? 'xh_green':'xh_red' ]">
</view>
<view @click.stop=""> <view @click.stop="">
<u-button type="success" size="small" text="一键刷新" /> <u-button type="success" size="small" text="一键刷新" />
</view> </view>
@ -166,15 +168,16 @@
<u-row v-if="item.deviceId"> <u-row v-if="item.deviceId">
<u-col span="4"> <u-col span="4">
<view class="fixed"> <view class="fixed">
<text class="font-green"></text> <text
<view>{{ item.rowKey }}</view> :class="[item.device.custom.online ? 'font-green':'font-red']"></text>
{{ item.rowKey }}
</view> </view>
</u-col> </u-col>
<u-col span="5"> <u-col span="5">
<view class="battery-container"> <view class="battery-container">
<text>60</text> <text>{{ item.device.custom.battery.value }}</text>
<view class="battery-level battery-level-60"> <view class="battery-level"
</view> :style="[`width:${item.device.custom.battery.value}%`]" />
</view> </view>
</u-col> </u-col>
<u-col span="3" style="align-items: flex-end;"> <u-col span="3" style="align-items: flex-end;">
@ -188,7 +191,11 @@
<view class="card-title"> <view class="card-title">
<u-row> <u-row>
<u-col span="2"> <u-col span="2">
<view><text class="font-green"></text>{{ item2.rowKey }}</view> <view>
<text
:class="[item2.device.custom.online ? 'font-green':'font-red']"></text>
{{ item2.rowKey }}
</view>
</u-col> </u-col>
<u-col span="5"> <u-col span="5">
<view class="fixed"> <view class="fixed">
@ -212,15 +219,23 @@
</u-row> </u-row>
</view> </view>
<view class="control"> <view class="control">
<!-- 三通阀 -->
<u-row <u-row
v-if="item2.device.deviceTypeId == 2 || item2.device.deviceTypeId == 3"> v-if="item2.device.deviceTypeId == 2 || item2.device.deviceTypeId == 3">
<u-col span="3" style=" align-items: flex-end;" <u-col span="3" style=" align-items: flex-end;"
@click="angleSliderShow"> @click="angleSliderShow">
<view class="buttons"> <view class="buttons">
<view class="btn fixed active"> <view class="btn v-btn fixed active ">
<text></text> <text></text>
<text>(999)</text> <text class="load-text">(999)</text>
<!-- <view class="iconfont icon-suoding icon"></view> --> <text class="load-text"
v-if="!item2.device.custom.btnPreload && item2.device.custom.btnState.closeAll.loading && item2.device.custom.ct.endS >= 0"
:class="item2.device.custom.ct.endS > 0 ? '' : 'loading-time-red'">
{{ item2.device.custom.ct.endS > 0 ? `(${item2.device.custom.ct.endS})` : "超时" }}
</text>
<view v-if="!item2.device.custom.btnControllable.open1"
class="iconfont icon-suoding icon">
</view>
</view> </view>
</view> </view>
<u-line-progress height="8" :showText="false" :percentage="60" <u-line-progress height="8" :showText="false" :percentage="60"
@ -231,54 +246,75 @@
<u-col span="6"> <u-col span="6">
<view class="valve"> <view class="valve">
<view> <view>
<view class="btn fixed"> <u-button>全开</u-button>
<!-- <view class="btn v-btn2 fixed">
<text>全开</text> <text>全开</text>
</view> <text class="load-text">(超时)</text>
<view
v-if="!item2.device.custom.btnControllable.openAll"
class="iconfont icon-suoding icon">
</view>
</view> -->
</view> </view>
<view class="btn-img"> <view class="btn-img">
<view class="text"> <view class="text">
<view class="left">{{ item2.device.custom.p1 }}</view> <view class="left">{{ item2.device.custom.p1 }}</view>
<view class="top"></view> <view class="top"></view>
<view class="middle" <view class="middle"
v-show="!item2.device.custom.online">离线</view> v-show="!item2.device.custom.online">
{{ item2.device.custom.showMask.text }}
</view>
<view class="right">{{ item2.device.custom.p2 }}</view> <view class="right">{{ item2.device.custom.p2 }}</view>
<view class="bottom"></view> <view class="bottom"></view>
</view> </view>
<image :src="item2.device.custom.showImg" mode="widthFix" /> <image :src="item2.device.custom.showImg" mode="widthFix" />
</view> </view>
<view> <view>
<view class="btn fixed"> <view class="btn v-btn2 fixed">
<text>全关</text> <text>全关</text>
<text class="load-text">(超时)</text>
<view
v-if="!item2.device.custom.btnControllable.closeAll"
class="iconfont icon-suoding icon">
</view>
</view> </view>
</view> </view>
</view> </view>
</u-col> </u-col>
<u-col span="3"> <u-col span="3">
<view class="buttons"> <view class="buttons">
<view class="btn fixed"> <view class="btn v-btn fixed activeing">
<text></text> <text></text>
<text>(超时)</text> <text class="load-text">(超时)</text>
<!-- <view class="iconfont icon-suoding icon"></view> --> <view v-if="!item2.device.custom.btnControllable.open2"
class="iconfont icon-suoding icon">
</view>
</view> </view>
</view> </view>
</u-col> </u-col>
</u-row> </u-row>
<!-- 五通阀 -->
<u-row v-if="item2.device.deviceTypeId == 13"> <u-row v-if="item2.device.deviceTypeId == 13">
<u-col span="3" style=" align-items: flex-end;"> <u-col span="3" style=" align-items: flex-end;">
<view class="buttons"> <view class="buttons">
<view class="btn fixed active"> <view class="btn v-btn fixed active">
<text></text> <text></text>
<text>0.00</text> <text class="load-text">(超时)</text>
<view class="iconfont icon-suoding icon"></view> <view v-if="!item2.device.custom.btnControllable.open1"
class="iconfont icon-suoding icon">
</view>
</view> </view>
</view> </view>
</u-col> </u-col>
<u-col span="6"> <u-col span="6">
<view class="valve"> <view class="valve">
<view> <view>
<view class="btn fixed"> <view class="btn v-btn fixed">
<text></text> <text></text>
<text class="load-text">(超时)</text>
<view v-if="!item2.device.custom.btnControllable.open2"
class="iconfont icon-suoding icon">
</view>
</view> </view>
</view> </view>
<view class="btn-img"> <view class="btn-img">
@ -286,7 +322,9 @@
<view class="left">{{ item2.device.custom.p[0] }}</view> <view class="left">{{ item2.device.custom.p[0] }}</view>
<view class="top">{{ item2.device.custom.p[1] }}</view> <view class="top">{{ item2.device.custom.p[1] }}</view>
<view class="middle" <view class="middle"
v-show="!item2.device.custom.online">离线</view> v-show="!item2.device.custom.online">
{{ item2.device.custom.showMask.text }}
</view>
<view class="right">{{ item2.device.custom.p[2] }} <view class="right">{{ item2.device.custom.p[2] }}
</view> </view>
<view class="bottom">{{ item2.device.custom.p[3] }} <view class="bottom">{{ item2.device.custom.p[3] }}
@ -295,24 +333,32 @@
<image :src="item2.device.custom.showImg" mode="widthFix" /> <image :src="item2.device.custom.showImg" mode="widthFix" />
</view> </view>
<view> <view>
<view class="btn fixed"> <view class="btn v-btn fixed">
<text></text> <text></text>
<text class="load-text">(超时)</text>
<view v-if="!item2.device.custom.btnControllable.open4"
class="iconfont icon-suoding icon">
</view>
</view> </view>
</view> </view>
</view> </view>
</u-col> </u-col>
<u-col span="3"> <u-col span="3">
<view class="buttons"> <view class="buttons">
<view class="btn fixed"> <view class="btn v-btn fixed">
<text></text> <text></text>
<text>0.00</text> <text class="load-text">(超时)</text>
<view class="iconfont icon-suoding icon"></view> <view v-if="!item2.device.custom.btnControllable.open3"
class="iconfont icon-suoding icon">
</view>
</view> </view>
</view> </view>
</u-col> </u-col>
</u-row> </u-row>
<view class="font-red"> <view class="font-red" v-if="item2.device.custom.showMask.show">
<view class="iconfont icon-guzhang icon"></view>角度4故障 <view class="iconfont icon-guzhang icon">
{{item2.device.custom.showMask.text}}
</view>
</view> </view>
</view> </view>
</view> </view>
@ -320,84 +366,7 @@
{{ item2.rowKey }} {{ item2.rowKey }}
</view> </view>
</view> </view>
<view class="card-grey" v-if="false">
<view class="card-title">
<u-row>
<u-col span="2">
<view><text class="font-green"></text>1-2</view>
</u-col>
<u-col span="5">
<view class="fixed">
<view class="battery-container">
<text>60</text>
<view class="battery-level battery-level-60">
</view>
</view>
<view>
<view class="iconfont icon-wendu icon"></view>26.2
</view>
</view>
</u-col>
<u-col span="5" style="align-items: flex-end;">
<view class="fixed">
<u-button type="success" size="mini" text="刷新"
icon="reload"></u-button>
</view>
</u-col>
</u-row>
</view>
<view class="control">
<u-row>
<u-col span="3" style=" align-items: flex-end;">
<view class="buttons">
<view class="btn fixed active">
<text></text>
<text>0.00</text>
<view class="iconfont icon-suoding icon"></view>
</view>
</view>
</u-col>
<u-col span="6">
<view class="valve">
<view>
<view class="btn fixed">
<text>全开</text>
</view>
</view>
<view class="btn-img">
<view class="text5">
<view class="left">-99.63</view>
<view class="top">-99.63</view>
<view class="middle">离线</view>
<view class="right">-99.63</view>
<view class="bottom">-99.63</view>
</view>
<!-- <image src="../static/images/fiveValves/valve5.png"
mode="widthFix">
</image> -->
</view>
<view>
<view class="btn fixed">
<text>全关</text>
</view>
</view>
</view>
</u-col>
<u-col span="3">
<view class="buttons">
<view class="btn fixed">
<text></text>
<text>0.00</text>
<view class="iconfont icon-suoding icon"></view>
</view>
</view>
</u-col>
</u-row>
</view>
</view>
</view> </view>
</u-collapse-item> </u-collapse-item>
</u-collapse> </u-collapse>
</view> </view>
@ -412,6 +381,14 @@
<!-- 角度 --> <!-- 角度 -->
<custom-angle-slider ref="refAngleSlider" mode="bottom" @close="" @confirm="angleSliderConfirm" /> <custom-angle-slider ref="refAngleSlider" mode="bottom" @close="" @confirm="angleSliderConfirm" />
</view> </view>
<button @click="mqttLink">mqttLink</button>
<button @click="mqttEnd">mqttEnd</button>
<button @click="mqttGet">获取信息</button>
<view>
<p>connected:{{mqtt.connected}}</p>
<!-- <p>reconnecting:{{mqtt.client.reconnecting}}</p>
<p>结果{{mqtt.client && (mqtt.client.connected && !mqtt.client.reconnecting)}}</p> -->
</view>
</template> </template>
<script> <script>
@ -420,23 +397,27 @@
export default { export default {
data() { data() {
return { return {
user: store.state.user.user,
isSticky: false, // isSticky: false, //
value: false, value: false,
indexData: getApp().indexData, indexData: getApp().indexData,
dc: getApp().dc, dc: getApp().dc,
// show: false, mqtt: getApp().mqtt,
isLandChange: false, isLandChange: false,
} }
}, },
onLoad() { onLoad() {
console.error("onLoad") console.error("onLoad")
// uni.$emit("mqtt-link"); // uni.$emit("mqtt-link", this.user.userId);
// getApp().mqttLink(this.user.userId);
uni.$off("notify-update-land"); uni.$off("notify-update-land");
uni.$on("notify-update-land", (data) => { uni.$on("notify-update-land", (data) => {
console.error("index监听地块更新", data) console.error("index监听地块更新", data)
this.isLandChange = true; this.isLandChange = true;
}); });
}, },
onShow() { onShow() {
// #ifdef APP-PLUS // #ifdef APP-PLUS
@ -454,6 +435,15 @@
} }
}, },
methods: { methods: {
mqttLink() {
getApp().mqttLink(this.user.userId);
},
mqttEnd() {
getApp().mqttEnd();
},
mqttGet() {
console.error("mqtt", this.mqtt)
},
// //
openLand() { openLand() {
this.$refs.refLand.open(); this.$refs.refLand.open();
@ -689,6 +679,19 @@
.u-row { .u-row {
margin-bottom: 10px; margin-bottom: 10px;
} }
.btn.v-btn {
width: 80px;
}
.btn.v-btn2 {
font-size: 12px;
width: 90px;
}
.buttons .load-text {
font-size: 12px;
}
} }
} }
@ -707,6 +710,14 @@
text { text {
font-size: 32rpx; font-size: 32rpx;
} }
// .icon-xh.xh_green {
// color: #39ac4f
// }
// .icon-xh.xh_red {
// color: #e60012
// }
} }
.sf-title { .sf-title {
@ -833,28 +844,11 @@
transition: width 0.5s; transition: width 0.5s;
} }
/* 不同的电量级别 */ .font-green {
.battery-level-100 { color: #39ac4f
width: 100%;
} }
.battery-level-80 { .font-red {
width: 80%; color: #e60012
}
.battery-level-60 {
width: 60%;
}
.battery-level-40 {
width: 40%;
}
.battery-level-20 {
width: 20%;
}
.battery-level-0 {
width: 0%;
} }
</style> </style>

View File

@ -1,66 +1,142 @@
import * as commonUtils from "@/utils/common.js"
// #ifdef H5
import mqtt from "mqtt/dist/mqtt" import mqtt from "mqtt/dist/mqtt"
// import mqtt from "@/store/modules/mqtt.js" // #endif
import store from "@/store" // #ifdef APP-PLUS
import {
connect,
subscribe,
unSubscribe,
getConfig,
onConnectLost,
onReconnect,
disConnect,
publishMessage
} from "@/uni_modules/zy-mqtt";
// #endif
//封装一个类可直接cv //封装一个类可直接cv
class MqttUtil { class MqttUtil {
//创建公共变量 //创建公共变量
static url //mqtt地址 static url;
static userId //userId static options;
static clientId //clientId static client;
static options //clientId static connected = false;
static client = null; //mqtt公共变量 static reconnectCount = 0;
//接收创建来的数据 //接收创建来的数据
constructor() { constructor(eventHandler) {
this.url = import.meta.env.VITE_BASE_MQTT; this.url = import.meta.env.VITE_BASE_MQTT;
// this.userId = store.state.user.user.userId; this.eventHandler = eventHandler;
this.clientId = "mqtt_app_" + this.getUUID(); }
//初始化参数
init(userId) {
let clientId = `mqtt_app_${userId}_${this.getUUID()}`;
let username = "app_client";
let password = "app_client@2023";
let keepalive = 10; //保持连接的心跳间隔,单位为秒。
let connectTimeout = 30; //接超时的时间,单位为秒。
// #ifdef H5
this.options = { this.options = {
qos: 1, //QoS 级别 clientId: clientId, // string 客户端的唯一标识符。
clean: false, // true: 清除会话, false: 保留会话 username: username, // string 连接时的用户名。
connectTimeout: 3000, // 超时时间 password: password, // string 连接时的密码。
keepAlive: 60, keepalive: keepalive, // number 60 保持连接的心跳间隔,单位为秒。
username: "app_client", clean: false, // boolean true 是否清除会话信息。false 时,断线重连后可继续接收未到达的消息。
password: "app_client@2023", reconnectPeriod: 1000, // number 1000 断开后重连的时间间隔,单位为毫秒。当设置为 0 以后将取消自动重连
clientId: this.clientId connectTimeout: connectTimeout * 1000, // number 30 * 1000 连接超时的时间,单位为毫秒。
// will: { // object 无 客户端的遗嘱消息。当客户端异常断开时broker 将会发送该消息。
// topic: '', // 发布消息的主题
// payload: '', // 要发布的消息
// qos: 0, // 消息等级
// retain: false // 保留消息标识
// },
// protocolId: "MQTT", // string MQTT 协议名称。
// protocolVersion: 4, // number MQTT 协议版本4 表示 MQTT v3.1.1。
resubscribe: true, // boolean true 断线重连后是否自动重新订阅之前的主题。
} }
// #endif
// #ifdef APP-PLUS
this.options = {
host: this.url, // 主机ip
clientId: clientId, // 客户端id
userName: username, // 用户名
password: password, // 密码
heartBeat: keepalive, // 可选,默认60秒, 心跳
cleanSession: false, // 可选,默认false,是否开启持续会话
automaticReconnect: true, // 可选,默认true,是否自动重连
timeOut: connectTimeout, // 可选,默认30秒,连接超时时间
keepAlive: false, // 可选,是否保活(息屏保活), 对于Android O及以上版本如果你的应用处于后台你需要将服务转变为前台服务来避免系统在一定时间后杀死服务。这需要通过创建一个持续在通知栏显示的通知来实现。
// notificationContentText, // 可选,通知内容,默认(应用正在后台运行,这有助于提供定制的服务和改善用户体验。)
// notificationContentTitle, // 可选,通知标题,默认(后台应用持续运行)
};
// #endif
}
//监听消息回调
onEventHandler(topic, data) {
// console.error("topic", topic);
// console.error("data", data);
this.eventHandler(topic, data);
// var message = JSON.stringify(res);
// // console.error("message:",message);
// if (x.includes("jsy/iot/control/")) {
// // uni.$emit("mqtt-message-refresh", message)
// } else {
// if (message !== "" && message !== null) {
// let str = JSON.parse(message)
// uni.$emit("mqtt-message", str)
// }
// }
}
getUUID() {
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
} }
// #ifdef H5
//mqtt链接 //mqtt链接
link() { link(userId) {
if (this.client == null || this.client.connented == false) { if (!this.options) {
let client = mqtt.connect(this.url, this.options); this.init(userId);
if (this.client == null) { }
this.client = client; console.error("link:", this.client)
console.error("开始连接")
this.client.on("connect", error => { this.client = mqtt.connect(this.url, this.options);
console.log("connect")
}) this.client.on("connect", error => {
this.client.on("error", error => { this.connected = this.client.connected && !this.client.reconnecting;
console.log("error") this.reconnectCount = 0;
}) console.error("消息连接成功:", this.client)
this.client.on("reconnect", error => { })
console.log("reconnect") this.client.on("reconnect", error => {
}) this.connected = this.client.connected && !this.client.reconnecting;
this.client.on("message", (topic, message) => { this.reconnectCount++;
console.log("message", message.toString()) console.error(`消息重连中${this.reconnectCount}`, this.client)
}) })
} this.client.on("error", error => {
} console.log("error", error)
} })
//重新连接 this.client.on("message", (topic, message) => {
reconnect() { console.log("接受消息")
if (this.client.connected) { console.log("message", message.toString())
this.client.end(); // 关闭当前连接 this.onEventHandler(topic, message);
} })
this.client.connect(this.options); // 重新连接 this.client.on("close", function() {
console.log("已断开连接1")
this.client = null;
this.connected = false;
this.reconnectCount = 0;
});
} }
//结束链接 //结束链接
over() { over() {
this.client.end(); this.client.end(false, null, () => {});
this.client = null;
} }
//订阅主题 //订阅主题
subscribes(topic) { subscribes(topic) {
@ -82,25 +158,79 @@ class MqttUtil {
} }
}) })
} }
//收到的消息 //发送消息
get() { send(message) {
this.mqtt.client.on("message", (topic, message) => { // this.client.publish("test", JSON.stringify(message), res => {
console.log("接受消息") // console.log(res)
console.log("message", message.toString()) // })
}
// #endif
// #ifdef APP-PLUS
//mqtt链接
link(userId) {
if (!this.options) {
this.init(userId);
}
console.error("link:")
console.error("开始连接")
// 先连接mqtt
connect(this.options, (res) => {
console.error("连接成功:", res);
if (res.code == 200) {
this.connected = true;
this.reconnectCount = 0;
console.error("消息连接成功:")
}
}) })
// 监听连接丢失函数
onConnectLost((res) => {
console.error("连接丢失的原因:", res.message);
this.connected = false;
})
// 监听自动重新连接函数
onReconnect((res) => {
// this.connected = this.client.connected && !this.client.reconnecting;
this.connected = true;
this.reconnectCount++;
console.error(`消息重连中${this.reconnectCount}`)
})
}
//结束链接
over() {
disConnect((res) => {
this.connected = false;
this.reconnectCount = 0;
})
}
//订阅主题
subscribes(topics) {
if (topics && topics.length) {
topics.forEach(x => {
subscribe(topic, 0, (res) => {
console.log("接受消息")
console.log("message", message.toString())
var message = JSON.stringify(res);
this.onEventHandler(topic, message);
})
});
}
}
//取消订阅
unsubscribes(topic) {
if (topic && topic.length) {
topic.forEach(x => {
unSubscribe(x, (res) => {})
});
}
} }
//发送消息 //发送消息
send(message) { send(message) {
this.client.publish("test", JSON.stringify(message), res => { // publishMessage('your/topic', 2, message, (res) => {
console.log(res) // })
})
}
getUUID() {
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
} }
// #endif
} }
export default MqttUtil export default MqttUtil