JavaScript开发温度传感小程序,从硬件端通过蓝牙读取温度数据并实时显示,在屏幕下端画出温度走势图。现在可以显示温度但是走势图没反应,能不能帮我看看是少写了什么?
// 在文件顶部添加引入语句
import * as echarts from '../../ec-canvas/echarts';
Page({
data: {
devices: [], // 设备列表数据
bluetoothStatus: '未连接',
bluetoothConnected: false,
currentTemp: null,
tempData: [],
ec: {} // 图表配置容器
},
onLoad() {
// 先加载历史数据,再初始化图表
this.loadHistory(() => {
this.initChart();
});
},
// 初始化蓝牙
initBluetooth() {
if (this.data.bluetoothConnected) {
this.closeBluetooth();
return;
}
wx.openBluetoothAdapter({
success: () => {
this.startDiscovery();
this.listenDeviceFound();
},
fail: (err) => this.showToast('蓝牙初始化失败: ' + err.errMsg)
});
},
// 开始设备发现
startDiscovery() {
wx.startBluetoothDevicesDiscovery({
allowDuplicatesKey: false,
success: () => this.showToast('正在搜索设备...'),
fail: (err) => this.showToast('搜索失败: ' + err.errMsg)
});
},
// 监听发现设备事件
listenDeviceFound() {
wx.onBluetoothDeviceFound(devices => {
if (!devices.devices) return;
// 过滤重复设备
const newDevices = devices.devices.filter(device =>
!this.data.devices.some(d => d.deviceId === device.deviceId)
);
this.setData({
devices: this.data.devices.concat(newDevices)
});
});
},
// 设备选择处理
selectDevice(e) {
const deviceId = e.currentTarget.dataset.deviceid;
this.connectDevice(deviceId);
},
// 连接设备
connectDevice(deviceId) {
wx.createBLEConnection({
deviceId,
success: () => {
this.setData({
bluetoothStatus: '已连接',
bluetoothConnected: true,
devices: [] // 清空设备列表
});
this.getService(deviceId);
},
fail: (err) => this.showToast('连接失败: ' + err.errMsg)
});
},
// 初始化图表
initChart() {
this.chartComponent = this.selectComponent('#chart');
// 确保图表配置初始化
this.option = {
title: {
text: '温度变化曲线',
left: 'center'
},
tooltip: {
trigger: 'axis'
},
xAxis: {
type: 'time',
splitLine: { show: false }
},
yAxis: {
type: 'value',
min:10,
max:30,
name: '温度(℃)'
},
series: [{
name: '温度',
type: 'line',
smooth: false,
linestyle: { //线颜色
color: '#000000',
width: 5,
},
itemstyle: { //数据点颜色
color: '#000000',
},
data: []
}]
};
this.setData({
ec: {
onInit: (canvas, width, height) => {
const chart = echarts.init(canvas, null, { width, height });
chart.setOption(this.option);
this.chartInstance = chart; // 保存实例
return chart;
}
}
});
},
// 加载历史数据
loadHistory(callback) {
// const history = wx.getStorageSync('tempHistory') || [];
// this.setData({ tempData: history }, () => {
// if (typeof callback === 'function') {
// callback(); // 数据加载完成后执行回调(初始化图表)
// }
// }); //这个是有存储功能的
const history = [];
this.setData({ tempData: history }, () => {
if (typeof callback === 'function') {
callback(); // 继续执行图表初始化回调
}
}); //这段用来测试阶段,删去了存储功能
},
// 更新图表数据(优化版)
updateChart(data) {
// 直接检查页面保存的图表实例
if (!this.chartInstance) {
console.warn('图表实例未初始化,延迟更新');
setTimeout(() => this.updateChart(data), 300);
return;
}
// 后续逻辑直接使用 this.chartInstance
const chartData = data.map(item => {
const timestamp = new Date(item.time).getTime();
return { name: item.time, value: [timestamp, item.temp] };
}).filter(item => !isNaN(item.value[0]));
const option = this.chartInstance.getOption();
if (option.series && option.series[0]) {
option.series[0].data = chartData;
// ... 动态Y轴逻辑 ...
this.chartInstance.setOption(option); // 直接用实例更新
}
},
// 监听数据变化
listenData(deviceId, serviceId, characteristicId) {
wx.notifyBLECharacteristicValueChange({
deviceId,
serviceId,
characteristicId,
state: true,
});
wx.onBLECharacteristicValueChange(res => {
// 打印原始数据用于调试
const uint8Arr = new Uint8Array(res.value);
console.log('原始字节数组:', Array.from(uint8Arr));
const rawHex = this.ab2hex(res.value);
console.log('原始16进制数据:', rawHex);
// 移除TextDecoder相关代码,使用兼容方式解析
// 数据解析逻辑(根据原始数据[21, 1] = 0x1501进行适配)
let temp = null;
// 针对2字节数据的解析(根据实际设备通信协议调整)
if (uint8Arr.length === 2) {
// 假设是16位无符号整数,小端模式,单位为0.1℃
const tempRaw = uint8Arr[0] + (uint8Arr[1] << 8);
temp = tempRaw / 10;
console.log('解析后的温度:', temp);
}
// 最终校验
if (!isNaN(temp) && temp >= -50 && temp <= 150) {
const time = new Date().toLocaleTimeString();
this.setData({ currentTemp: temp.toFixed(1) });
this.saveData({ temp, time });
} else {
console.warn('无法解析有效温度', { rawHex });
}
});
},
// 保存数据
saveData(data) {
// const newData = [...this.data.tempData, data];
// this.setData({ tempData: newData });
// wx.setStorageSync('tempHistory', newData);
// this.updateChart(newData); //同样,这里也是为了调试而删去存储功能
const newData = [...this.data.tempData, data];
this.setData({ tempData: newData });
this.updateChart(newData);
},
// 清除历史数据(增加图表初始化检查)
clearHistory() {
// this.setData({ tempData: [], currentTemp: null });
// wx.removeStorageSync('tempHistory');
// // 确保图表已初始化
// if (this.option) {
// this.updateChart([]);
// } //不必多言
this.setData({ tempData: [], currentTemp: null });
if (this.option) {
this.updateChart([]);
}
},
// ArrayBuffer转16进制字符串
ab2hex(buffer) {
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
},
// 关闭蓝牙连接
closeBluetooth() {
wx.closeBluetoothAdapter();
this.setData({
bluetoothStatus: '未连接',
bluetoothConnected: false
});
},
// 显示提示
showToast(title) {
wx.showToast({ title, icon: 'none' });
},
// 获取服务
getService(deviceId) {
wx.getBLEDeviceServices({
deviceId,
success: (res) => {
if (res.services && res.services.length > 0) {
console.log("所有服务列表:", res.services);
// 筛选出Unknown Service(排除标准服务UUID)
const unknownService = res.services.find(service =>
!service.uuid.includes('1800') && !service.uuid.includes('1801')
);
if (unknownService) {
this.getCharacteristics(deviceId, unknownService.uuid);
} else {
// 找不到则使用第一个服务
const serviceId = res.services[0].uuid;
this.getCharacteristics(deviceId, serviceId);
}
} else {
this.showToast('未找到可用服务');
}
},
fail: (err) => this.showToast('获取服务失败: ' + err.errMsg)
});
},
// 获取特征值(放宽筛选条件)
getCharacteristics(deviceId, serviceId) {
wx.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success: (res) => {
if (res.characteristics && res.characteristics.length > 0) {
console.log("所有特征值:", res.characteristics.map(c => c.uuid));
// 优先选择支持通知且可读写的特征值
const targetChar = res.characteristics.find(c =>
c.properties.notify && (c.properties.read || c.properties.write)
);
if (targetChar) {
this.listenData(deviceId, serviceId, targetChar.uuid);
} else {
// 退而求其次选择第一个可用特征值
const firstChar = res.characteristics.find(c =>
c.properties.notify || c.properties.read
);
if (firstChar) {
this.listenData(deviceId, serviceId, firstChar.uuid);
} else {
this.showToast('未找到可用特征值');
}
}
}
},
fail: (err) => this.showToast('获取特征值失败: ' + err.errMsg)
});
}
});
