Files
SmartPetFeeder_STM32/wex_small/pages/index/index.js

502 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// index.js
Page({
data: {
// 导航栏高度数据
navBarHeight: getApp().globalData.navBarHeight,
statusBarHeight: getApp().globalData.statusBarHeight,
menuBottom: getApp().globalData.menuBottom,
menuHeight: getApp().globalData.menuHeight,
// MQTT 连接状态
mqttStatus: '未连接',
isConnected: false,
// 数据显示
temperature: '--',
humidity: '--',
foodWeight: 0,
waterLevel: 0,
systemMode: 'auto', // auto: 自动, manual: 手动
// 设置数据
feedTimes: [], // 喂食时间点
singleFeedWeight: 50, // 单次喂食重量(克)
// 弹窗控制
showTimePicker: false,
showSettings: false,
currentEditingTimeIndex: -1,
// 加载状态
loading: false,
// 消息日志
messages: [],
// MQTT 主题
topics: {
sensor: 'petfeeder/sensor', // 传感器数据
control: 'petfeeder/control', // 控制指令
config: 'petfeeder/config', // 配置更新
status: 'petfeeder/status' // 状态查询
}
},
onLoad() {
// 获取导航栏高度数据
const app = getApp();
this.setData({
navBarHeight: app.globalData.navBarHeight,
statusBarHeight: app.globalData.statusBarHeight,
menuBottom: app.globalData.menuBottom,
menuHeight: app.globalData.menuHeight
});
// 页面加载时获取MQTT连接状态
this.updateConnectionStatus();
// 加载保存的设置
this.loadSettings();
// 请求当前状态
this.requestStatus();
// 延迟检查连接状态确保MQTT初始化完成
setTimeout(() => {
this.updateConnectionStatus();
}, 1000);
},
onShow() {
// 页面显示时更新状态
this.updateConnectionStatus();
},
/**
* 更新连接状态
*/
updateConnectionStatus() {
const app = getApp();
const isConnected = app.globalData.isMQTTConnected;
console.log('更新连接状态:', isConnected);
this.setData({
isConnected: isConnected,
mqttStatus: isConnected ? '已连接' : '未连接'
});
},
/**
* MQTT消息回调函数
*/
onMQTTMessage(topic, message) {
try {
const messageStr = message.toString().trim();
const messageData = JSON.parse(messageStr);
console.log('收到MQTT消息:', topic, messageData);
// 更新连接状态(收到消息说明连接正常)
const app = getApp();
this.setData({
isConnected: app.globalData.isMQTTConnected,
mqttStatus: app.globalData.isMQTTConnected ? '已连接' : '未连接'
});
// 处理传感器数据
if (topic.includes('sensor')) {
this.handleSensorData(messageData);
}
// 处理状态数据
else if (topic.includes('status')) {
this.handleStatusData(messageData);
}
// 处理配置确认
else if (topic.includes('config')) {
this.handleConfigResponse(messageData);
}
// 添加到消息日志
this.addMessageLog(topic, messageStr);
} catch (error) {
console.error('处理MQTT消息失败:', error);
}
},
/**
* 处理传感器数据
*/
handleSensorData(data) {
console.log('处理传感器数据:', data);
console.log('当前页面数据:', this.data);
this.setData({
temperature: data.temperature || '--',
humidity: data.humidity || '--',
foodWeight: data.foodWeight || 0,
waterLevel: data.waterLevel || 0
}, () => {
console.log('setData 回调执行完成');
console.log('更新后页面数据:', this.data);
});
},
/**
* 处理状态数据
*/
handleStatusData(data) {
if (data.mode) {
this.setData({
systemMode: data.mode
});
}
},
/**
* 处理配置响应
*/
handleConfigResponse(data) {
if (data.success) {
wx.showToast({
title: '配置保存成功',
icon: 'success'
});
} else {
wx.showToast({
title: '配置保存失败',
icon: 'error'
});
}
},
/**
* 添加消息日志
*/
addMessageLog(topic, message) {
const logItem = {
topic: topic,
message: message,
time: new Date().toLocaleTimeString()
};
const messages = this.data.messages;
messages.unshift(logItem);
if (messages.length > 10) {
messages.pop();
}
this.setData({ messages });
},
/**
* 切换系统模式
*/
toggleMode() {
const newMode = this.data.systemMode === 'auto' ? 'manual' : 'auto';
// 先发送控制命令成功后再更新UI
const sent = this.sendControlCommand({
action: 'setMode',
mode: newMode
});
if (sent) {
this.setData({ systemMode: newMode });
}
},
/**
* 手动喂食
*/
manualFeed() {
if (this.data.systemMode === 'auto') {
wx.showModal({
title: '提示',
content: '当前为自动模式,是否要切换到手动模式进行喂食?',
success: (res) => {
if (res.confirm) {
this.toggleMode();
setTimeout(() => {
this.executeFeed();
}, 500);
}
}
});
} else {
this.executeFeed();
}
},
/**
* 执行喂食命令
*/
executeFeed() {
this.sendControlCommand({
action: 'feed',
amount: this.data.singleFeedWeight
});
wx.showToast({
title: `喂食${this.data.singleFeedWeight}`,
icon: 'loading',
duration: 2000
});
},
/**
* 手动补水
*/
manualWater() {
this.sendControlCommand({
action: 'addWater'
});
wx.showToast({
title: '补水中...',
icon: 'loading',
duration: 3000
});
},
/**
* 刷新数据
*/
refreshData() {
this.setData({ loading: true });
// 请求最新数据
this.requestStatus();
setTimeout(() => {
this.setData({ loading: false });
wx.showToast({
title: '数据已刷新',
icon: 'success'
});
}, 1000);
},
/**
* 发送控制命令
*/
sendControlCommand(command) {
const app = getApp();
if (!app.globalData.isMQTTConnected) {
wx.showToast({
title: 'MQTT未连接',
icon: 'none'
});
return false;
}
const message = {
...command,
timestamp: new Date().toISOString()
};
return app.publishMQTT(this.data.topics.control, message);
},
/**
* 请求状态
*/
requestStatus() {
this.sendControlCommand({
action: 'getStatus'
});
},
/**
* 打开设置
*/
openSettings() {
this.setData({ showSettings: true });
},
/**
* 关闭设置
*/
closeSettings() {
this.setData({ showSettings: false });
},
/**
* 添加喂食时间
*/
addFeedTime() {
if (this.data.feedTimes.length >= 2) {
wx.showToast({
title: '最多设置2个时间点',
icon: 'none'
});
return;
}
this.setData({ currentEditingTimeIndex: -1, showTimePicker: true });
},
/**
* 编辑喂食时间
*/
editFeedTime(e) {
const index = e.currentTarget.dataset.index;
this.setData({
currentEditingTimeIndex: index,
showTimePicker: true
});
},
/**
* 删除喂食时间
*/
deleteFeedTime(e) {
const index = e.currentTarget.dataset.index;
const feedTimes = this.data.feedTimes;
feedTimes.splice(index, 1);
this.setData({ feedTimes });
},
/**
* 时间选择确认
*/
onTimeConfirm(e) {
console.log('时间选择返回值:', e.detail);
const time = e.detail;
let hours, minutes;
// type="time" 时Vant 返回的可能是对象、字符串或数组
if (Array.isArray(time)) {
// 如果是数组格式 [hours, minutes]
hours = time[0];
minutes = time[1];
} else if (typeof time === 'object' && time !== null) {
// 如果是对象格式 { hours, minutes } 或 { hour, minute }
hours = time.hours !== undefined ? time.hours : time.hour;
minutes = time.minutes !== undefined ? time.minutes : time.minute;
} else if (typeof time === 'string' && time.includes(':')) {
// 如果是字符串格式 "HH:mm"
const parts = time.split(':');
hours = parseInt(parts[0], 10);
minutes = parseInt(parts[1], 10);
} else {
// 其他情况作为时间戳处理
const date = new Date(time);
hours = date.getHours();
minutes = date.getMinutes();
}
console.log('解析结果 hours:', hours, 'minutes:', minutes);
const timeString = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
console.log('时间字符串:', timeString);
const feedTimes = this.data.feedTimes;
if (this.data.currentEditingTimeIndex === -1) {
// 新增
feedTimes.push(timeString);
feedTimes.sort();
} else {
// 编辑
feedTimes[this.data.currentEditingTimeIndex] = timeString;
feedTimes.sort();
}
this.setData({
feedTimes,
showTimePicker: false,
currentEditingTimeIndex: -1
});
},
/**
* 时间选择取消
*/
onTimeCancel() {
this.setData({
showTimePicker: false,
currentEditingTimeIndex: -1
});
},
/**
* 单次喂食重量改变
*/
onFeedWeightChange(e) {
this.setData({
singleFeedWeight: e.detail
});
},
/**
* 保存设置
*/
saveSettings() {
const config = {
feedTimes: this.data.feedTimes,
singleFeedWeight: this.data.singleFeedWeight
};
// 发送配置到设备
const app = getApp();
if (app.globalData.isMQTTConnected) {
app.publishMQTT(this.data.topics.config, config);
}
// 保存到本地存储
wx.setStorageSync('petfeeder_config', config);
this.setData({ showSettings: false });
wx.showToast({
title: '设置已保存',
icon: 'success'
});
},
/**
* 加载设置
*/
loadSettings() {
const config = wx.getStorageSync('petfeeder_config');
if (config) {
this.setData({
feedTimes: config.feedTimes || [],
singleFeedWeight: config.singleFeedWeight || 50
});
}
},
/**
* 格式化水位显示
*/
getWaterLevelText(level) {
return level === 1 ? '满水' : '缺水';
},
getWaterLevelType(level) {
return level === 1 ? 'success' : 'danger';
},
/**
* 格式化模式显示
*/
getModeText(mode) {
return mode === 'auto' ? '自动模式' : '手动模式';
},
/**
* 格式化模式类型
*/
getModeType(mode) {
return mode === 'auto' ? 'success' : 'primary';
}
});