| | |
| | | // pages/stationMonitor/stationMonitor.js |
| | | const { get } = require('../../api/request.js'); |
| | | const { |
| | | get |
| | | } = require('../../api/request.js'); |
| | | |
| | | Page({ |
| | | |
| | |
| | | data: { |
| | | activeTab: 'weather', // 默认选中气象站 |
| | | cameraList: [], |
| | | isLoading: false |
| | | isLoading: false, |
| | | // 气象站相关数据 |
| | | weatherStationList: [], |
| | | selectedWeatherStationIndex: 0, |
| | | currentWeatherStation: null, |
| | | // 水肥机相关数据 |
| | | fertilizerStationList: [], |
| | | selectedFertilizerStationIndex: 0, |
| | | currentFertilizerStation: null, |
| | | // 土壤墒情站相关数据 |
| | | soilStationList: [], |
| | | selectedSoilStationIndex: 0, |
| | | currentSoilStation: null, |
| | | //摄像头相关 |
| | | accessToken: 'at.4l27eilo2x0euquw4yrhjxnz9kvr294l-2dp10mcwig-1nnzr8p-7wp71d2bk', |
| | | hslUrl: '', |
| | | // 设备信息 |
| | | deviceInfo: null, |
| | | isRealDevice: false, |
| | | deviceSpecificConfig: { |
| | | videoHeight: 400, |
| | | buttonHeight: 72, |
| | | fontSize: 26 |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 生命周期函数--监听页面加载 |
| | | */ |
| | | onLoad(options) { |
| | | // 检测设备类型和屏幕信息 |
| | | this.detectDeviceInfo(); |
| | | |
| | | // 页面加载时获取摄像头信息 |
| | | this.getCameraList(); |
| | | // 获取所有设备信息(气象站、土壤墒情站、水肥机) |
| | | this.getAllDeviceInfo(); |
| | | }, |
| | | |
| | | /** |
| | | * 检测设备信息 |
| | | */ |
| | | detectDeviceInfo() { |
| | | try { |
| | | const systemInfo = wx.getSystemInfoSync(); |
| | | console.log('设备信息:', systemInfo); |
| | | |
| | | // 检测是否为真机 |
| | | const isRealDevice = systemInfo.platform === 'android' || systemInfo.platform === 'ios'; |
| | | |
| | | // 检测屏幕尺寸 |
| | | const screenWidth = systemInfo.screenWidth; |
| | | const screenHeight = systemInfo.screenHeight; |
| | | const pixelRatio = systemInfo.pixelRatio; |
| | | |
| | | // 检测微信版本 |
| | | const version = systemInfo.version; |
| | | |
| | | this.setData({ |
| | | deviceInfo: { |
| | | platform: systemInfo.platform, |
| | | isRealDevice: isRealDevice, |
| | | screenWidth: screenWidth, |
| | | screenHeight: screenHeight, |
| | | pixelRatio: pixelRatio, |
| | | version: version, |
| | | model: systemInfo.model, |
| | | system: systemInfo.system |
| | | } |
| | | }); |
| | | |
| | | console.log('设备检测结果:', { |
| | | isRealDevice, |
| | | screenWidth, |
| | | screenHeight, |
| | | pixelRatio, |
| | | version |
| | | }); |
| | | |
| | | // 根据设备信息调整布局 |
| | | this.adjustLayoutForDevice(); |
| | | |
| | | } catch (error) { |
| | | console.error('获取设备信息失败:', error); |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 根据设备信息调整布局 |
| | | */ |
| | | adjustLayoutForDevice() { |
| | | const { deviceInfo } = this.data; |
| | | if (!deviceInfo) return; |
| | | |
| | | // 真机特殊处理 |
| | | if (deviceInfo.isRealDevice) { |
| | | console.log('检测到真机,应用特殊优化'); |
| | | |
| | | // 真机上可能需要调整一些参数 |
| | | this.setData({ |
| | | isRealDevice: true, |
| | | // 可以根据设备信息调整其他参数 |
| | | deviceSpecificConfig: { |
| | | videoHeight: deviceInfo.screenHeight < 700 ? 320 : 400, |
| | | buttonHeight: deviceInfo.screenHeight < 700 ? 64 : 72, |
| | | fontSize: deviceInfo.pixelRatio > 2 ? 24 : 26 |
| | | } |
| | | }); |
| | | } else { |
| | | console.log('检测到模拟器'); |
| | | this.setData({ |
| | | isRealDevice: false |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | /** |
| | |
| | | * 生命周期函数--监听页面显示 |
| | | */ |
| | | onShow() { |
| | | |
| | | console.log('=== 页面显示 ==='); |
| | | console.log('当前页面数据:', { |
| | | activeTab: this.data.activeTab, |
| | | cameraList: this.data.cameraList, |
| | | deviceInfo: this.data.deviceInfo, |
| | | deviceSpecificConfig: this.data.deviceSpecificConfig |
| | | }); |
| | | |
| | | // 检查ezplayer组件的状态 |
| | | if (this.data.activeTab === 'camera') { |
| | | console.log('摄像头页面激活,检查组件状态'); |
| | | this.data.cameraList.forEach(camera => { |
| | | console.log(`摄像头 ${camera.name} 状态:`, { |
| | | id: camera.id, |
| | | online: camera.online, |
| | | hslUrl: camera.hslUrl, |
| | | isLoadingUrl: camera.isLoadingUrl, |
| | | urlError: camera.urlError, |
| | | isPlaying: camera.isPlaying |
| | | }); |
| | | }); |
| | | } |
| | | }, |
| | | |
| | | /** |
| | |
| | | * 页面相关事件处理函数--监听用户下拉动作 |
| | | */ |
| | | onPullDownRefresh() { |
| | | // 下拉刷新时重新获取摄像头列表 |
| | | // 下拉刷新时重新获取数据 |
| | | if (this.data.activeTab === 'camera') { |
| | | this.getCameraList(); |
| | | } else if (this.data.activeTab === 'weather' || this.data.activeTab === 'soil' || this.data.activeTab === 'fertilizer') { |
| | | this.getAllDeviceInfo(); |
| | | } |
| | | wx.stopPullDownRefresh(); |
| | | }, |
| | |
| | | this.setData({ |
| | | activeTab: tab |
| | | }); |
| | | |
| | | |
| | | // 如果切换到摄像头选项卡,确保有数据 |
| | | if (tab === 'camera' && this.data.cameraList.length === 0) { |
| | | this.getCameraList(); |
| | | } |
| | | |
| | | // 如果切换到气象站选项卡,确保有数据 |
| | | if (tab === 'weather' && this.data.weatherStationList.length === 0) { |
| | | this.getAllDeviceInfo(); |
| | | } |
| | | |
| | | // 如果切换到土壤墒情站选项卡,确保有数据 |
| | | if (tab === 'soil' && this.data.soilStationList.length === 0) { |
| | | this.getAllDeviceInfo(); |
| | | } |
| | | |
| | | // 如果切换到水肥机选项卡,确保有数据 |
| | | if (tab === 'fertilizer' && this.data.fertilizerStationList.length === 0) { |
| | | this.getAllDeviceInfo(); |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 获取所有设备信息(气象站、土壤墒情站、水肥机) |
| | | */ |
| | | getAllDeviceInfo() { |
| | | const app = getApp(); |
| | | |
| | | // 检查登录状态 |
| | | if (!app.globalData.isLoggedIn) { |
| | | wx.showToast({ |
| | | title: '请先登录', |
| | | icon: 'error' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | console.log('开始调用 /wx/mqtt/allSimple 接口获取设备信息'); |
| | | |
| | | get({url: '/wx/mqtt/allSimple'}) |
| | | .then(response => { |
| | | console.log('设备信息接口返回数据:', response); |
| | | |
| | | if (response.success && response.code === '0001') { |
| | | const content = response.content; |
| | | |
| | | // 处理气象站数据 |
| | | if (content.weathers && content.weathers.length > 0) { |
| | | const weatherStations = content.weathers.map(item => ({ |
| | | id: item.id, |
| | | name: item.name, |
| | | no: item.no, |
| | | online: true, // 默认在线 |
| | | location: '甘肃省民勤县', // 默认位置 |
| | | lastUpdate: new Date().toLocaleString() |
| | | })); |
| | | |
| | | this.setData({ |
| | | weatherStationList: weatherStations |
| | | }); |
| | | |
| | | // 默认选择第一个气象站 |
| | | if (weatherStations.length > 0) { |
| | | this.selectWeatherStation(0); |
| | | } |
| | | } |
| | | |
| | | // 处理土壤墒情站数据 |
| | | if (content.soils && content.soils.length > 0) { |
| | | const soilStations = content.soils.map(item => ({ |
| | | id: item.id, |
| | | name: item.name, |
| | | no: item.no, |
| | | online: true, // 默认在线 |
| | | location: '甘肃省民勤县', // 默认位置 |
| | | lastUpdate: new Date().toLocaleString() |
| | | })); |
| | | |
| | | this.setData({ |
| | | soilStationList: soilStations |
| | | }); |
| | | |
| | | // 默认选择第一个土壤墒情站 |
| | | if (soilStations.length > 0) { |
| | | this.selectSoilStation(0); |
| | | } |
| | | } |
| | | |
| | | // 处理水肥机数据 |
| | | if (content.manures && content.manures.length > 0) { |
| | | const fertilizerStations = content.manures.map(item => ({ |
| | | id: item.id, |
| | | name: item.name, |
| | | no: item.no, |
| | | online: true // 默认在线 |
| | | })); |
| | | |
| | | this.setData({ |
| | | fertilizerStationList: fertilizerStations |
| | | }); |
| | | |
| | | // 默认选择第一个水肥机 |
| | | if (fertilizerStations.length > 0) { |
| | | this.selectFertilizerStation(0); |
| | | } |
| | | } |
| | | |
| | | console.log('设备信息处理完成:', { |
| | | weatherStations: this.data.weatherStationList, |
| | | soilStations: this.data.soilStationList, |
| | | fertilizerStations: this.data.fertilizerStationList |
| | | }); |
| | | |
| | | } else { |
| | | console.error('获取设备信息失败:', response.msg); |
| | | wx.showToast({ |
| | | title: response.msg || '获取设备信息失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error('调用设备信息接口失败:', error); |
| | | wx.showToast({ |
| | | title: '获取设备信息失败', |
| | | icon: 'error' |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | |
| | | */ |
| | | getCameraList() { |
| | | const app = getApp(); |
| | | |
| | | |
| | | // 检查登录状态 |
| | | if (!app.globalData.isLoggedIn) { |
| | | wx.showToast({ |
| | |
| | | isLoading: true |
| | | }); |
| | | |
| | | // 模拟接口返回数据 |
| | | setTimeout(() => { |
| | | const mockResponse = { |
| | | "code": "0001", |
| | | "content": { |
| | | "itemTotal": 4, |
| | | "obj": [ |
| | | { |
| | | "id": "2025070715040300007", |
| | | "name": "民勤01", |
| | | "videoUrl4PcLive": "https://open.ys7.com/console/jssdk/pc.html?url=ezopen://open.ys7.com/FX6737162/1.live&accessToken=at.2o04glgs0q36cjugbvddqujz7tqrghx1-1ovr6lmf3k-03pij3c-304ziif7e&themeId=pcLive&env=&date=", |
| | | "videoUrl4Security": "https://open.ys7.com/console/jssdk/pc.html?accessToken=at.87a8u4z04s3gom0o6i0cpgz35kuhu8xh-67xrfkiy90-0nnbl6z-r0v9mckp3&url=ezopen://open.ys7.com/FY4056878/1.live&themeId=security&date=", |
| | | "videoUrl4Simple": "https://open.ys7.com/console/jssdk/pc.html?accessToken=at.87a8u4z04s3gom0o6i0cpgz35kuhu8xh-67xrfkiy90-0nnbl6z-r0v9mckp3&url=ezopen://open.ys7.com/FY4056878/1.live&themeId=simple&date=", |
| | | "videoUrl4Standard": "https://open.ys7.com/console/jssdk/pc.html?accessToken=at.87a8u4z04s3gom0o6i0cpgz35kuhu8xh-67xrfkiy90-0nnbl6z-r0v9mckp3&url=ezopen://open.ys7.com/FY4056878/1.live&themeId=standard&date=" |
| | | }, |
| | | { |
| | | "id": "2025070715040300008", |
| | | "name": "民勤02", |
| | | "videoUrl4PcLive": "https://open.ys7.com/console/jssdk/pc.html?url=ezopen://open.ys7.com/FY4056879/1.live&accessToken=at.87a8u4z04s3gom0o6i0cpgz35kuhu8xh-67xrfkiy90-0nnbl6z-r0v9mckp3&themeId=pcLive&env=&date=", |
| | | "videoUrl4Security": "https://open.ys7.com/console/jssdk/pc.html?accessToken=at.87a8u4z04s3gom0o6i0cpgz35kuhu8xh-67xrfkiy90-0nnbl6z-r0v9mckp3&url=ezopen://open.ys7.com/FY4056879/1.live&themeId=security&date=", |
| | | "videoUrl4Simple": "https://open.ys7.com/console/jssdk/pc.html?accessToken=at.87a8u4z04s3gom0o6i0cpgz35kuhu8xh-67xrfkiy90-0nnbl6z-r0v9mckp3&url=ezopen://open.ys7.com/FY4056879/1.live&themeId=simple&date=", |
| | | "videoUrl4Standard": "https://open.ys7.com/console/jssdk/pc.html?accessToken=at.87a8u4z04s3gom0o6i0cpgz35kuhu8xh-67xrfkiy90-0nnbl6z-r0v9mckp3&url=ezopen://open.ys7.com/FY4056879/1.live&themeId=standard&date=" |
| | | }, |
| | | { |
| | | "id": "2025070715040300009", |
| | | "name": "民勤03", |
| | | "videoUrl4PcLive": "https://open.ys7.com/console/jssdk/pc.html?url=ezopen://open.ys7.com/FY4056880/1.live&accessToken=at.87a8u4z04s3gom0o6i0cpgz35kuhu8xh-67xrfkiy90-0nnbl6z-r0v9mckp3&themeId=pcLive&env=&date=", |
| | | "videoUrl4Security": "https://open.ys7.com/console/jssdk/pc.html?accessToken=at.87a8u4z04s3gom0o6i0cpgz35kuhu8xh-67xrfkiy90-0nnbl6z-r0v9mckp3&url=ezopen://open.ys7.com/FY4056880/1.live&themeId=security&date=", |
| | | "videoUrl4Simple": "https://open.ys7.com/console/jssdk/pc.html?accessToken=at.87a8u4z04s3gom0o6i0cpgz35kuhu8xh-67xrfkiy90-0nnbl6z-r0v9mckp3&url=ezopen://open.ys7.com/FY4056880/1.live&themeId=simple&date=", |
| | | "videoUrl4Standard": "https://open.ys7.com/console/jssdk/pc.html?accessToken=at.87a8u4z04s3gom0o6i0cpgz35kuhu8xh-67xrfkiy90-0nnbl6z-r0v9mckp3&url=ezopen://open.ys7.com/FY4056880/1.live&themeId=standard&date=" |
| | | }, |
| | | { |
| | | "id": "2025070715040300010", |
| | | "name": "民勤04", |
| | | "videoUrl4PcLive": "https://open.ys7.com/console/jssdk/pc.html?url=ezopen://open.ys7.com/FY4056881/1.live&accessToken=at.87a8u4z04s3gom0o6i0cpgz35kuhu8xh-67xrfkiy90-0nnbl6z-r0v9mckp3&themeId=pcLive&env=&date=", |
| | | "videoUrl4Security": "https://open.ys7.com/console/jssdk/pc.html?accessToken=at.87a8u4z04s3gom0o6i0cpgz35kuhu8xh-67xrfkiy90-0nnbl6z-r0v9mckp3&url=ezopen://open.ys7.com/FY4056881/1.live&themeId=security&date=", |
| | | "videoUrl4Simple": "https://open.ys7.com/console/jssdk/pc.html?accessToken=at.87a8u4z04s3gom0o6i0cpgz35kuhu8xh-67xrfkiy90-0nnbl6z-r0v9mckp3&url=ezopen://open.ys7.com/FY4056881/1.live&themeId=simple&date=", |
| | | "videoUrl4Standard": "https://open.ys7.com/console/jssdk/pc.html?accessToken=at.87a8u4z04s3gom0o6i0cpgz35kuhu8xh-67xrfkiy90-0nnbl6z-r0v9mckp3&url=ezopen://open.ys7.com/FY4056881/1.live&themeId=standard&date=" |
| | | } |
| | | ], |
| | | "pageCurr": 1, |
| | | "pageSize": 4, |
| | | "pageTotal": 1 |
| | | }, |
| | | "msg": "请求成功", |
| | | "success": true |
| | | }; |
| | | // 调用真实接口获取摄像头列表 |
| | | this.getVideoListFromApi(); |
| | | }, |
| | | |
| | | console.log('模拟接口返回数据:', mockResponse); |
| | | |
| | | if (mockResponse.success && mockResponse.code === '0001') { |
| | | // 处理返回的摄像头数据 |
| | | const cameraList = mockResponse.content.obj.map(item => { |
| | | // 从萤石云URL中提取设备信息并生成RTMP地址 |
| | | let rtmpUrl = ''; |
| | | |
| | | if (item.videoUrl4PcLive) { |
| | | // 提取设备序列号和通道号 |
| | | const ezopenMatch = item.videoUrl4PcLive.match(/ezopen:\/\/open\.ys7\.com\/([^\/]+)\/(\d+)\.live/); |
| | | const tokenMatch = item.videoUrl4PcLive.match(/accessToken=([^&]+)/); |
| | | /** |
| | | * 从接口获取视频列表 |
| | | */ |
| | | getVideoListFromApi() { |
| | | console.log('开始调用 /wx/video/all 接口获取视频列表'); |
| | | |
| | | get({url:'/wx/video/all'} ) |
| | | .then(response => { |
| | | console.log('接口返回数据:', response); |
| | | |
| | | if (response.success && response.code === '0001') { |
| | | // 处理返回的摄像头数据 |
| | | const cameraList = response.content.map(item => { |
| | | // 根据devNo生成RTMP URL |
| | | const channelNo = 1; // 默认通道号 |
| | | const rtmpUrl = `rtmp://open.ys7.com/${item.devNo}/${channelNo}/live`; |
| | | |
| | | if (ezopenMatch && tokenMatch) { |
| | | const deviceSerial = ezopenMatch[1]; // 设备序列号 |
| | | const channelNo = ezopenMatch[2]; // 通道号 |
| | | const accessToken = tokenMatch[1]; // 访问令牌 |
| | | |
| | | // 生成RTMP地址 |
| | | rtmpUrl = `rtmp://open.ys7.com:1935/live/${deviceSerial}/${channelNo}?accessToken=${accessToken}`; |
| | | |
| | | // 备用HLS地址 |
| | | const hlsUrl = `https://open.ys7.com:443/live/${deviceSerial}/${channelNo}.m3u8?accessToken=${accessToken}`; |
| | | |
| | | console.log('生成的RTMP地址:', rtmpUrl); |
| | | console.log('生成的HLS地址:', hlsUrl); |
| | | } |
| | | } |
| | | console.log(`摄像头 ${item.name} 生成RTMP URL:`, rtmpUrl); |
| | | |
| | | return { |
| | | id: item.id, |
| | | name: item.name, |
| | | onLine: true, // 默认在线,实际项目中可能需要额外的状态检查 |
| | | lastUpdate: new Date().toLocaleString(), // 当前时间作为最后更新时间 |
| | | isPlaying: false, // 视频播放状态 |
| | | hslUrl: rtmpUrl, // 使用生成的RTMP URL |
| | | deviceSerial: item.devNo, // 使用接口返回的devNo |
| | | isLoadingUrl: false, // URL加载状态 |
| | | urlError: false, // URL获取错误状态 |
| | | autoPlay: false, // 自动播放控制 |
| | | // 新增字段 |
| | | lng: item.lng, // 经度 |
| | | lat: item.lat, // 纬度 |
| | | accessToken: item.accessToken // 设备专用accessToken |
| | | }; |
| | | }); |
| | | |
| | | this.setData({ |
| | | cameraList: cameraList, |
| | | isLoading: false |
| | | }); |
| | | |
| | | console.log('处理后的摄像头列表:', cameraList); |
| | | |
| | | return { |
| | | id: item.id, |
| | | name: item.name, |
| | | online: true, // 默认在线,实际项目中可能需要额外的状态检查 |
| | | thumbnail: '/images/camera-thumb1.jpg', // 默认缩略图 |
| | | lastUpdate: new Date().toLocaleString(), // 当前时间作为最后更新时间 |
| | | isPlaying: false, // 视频播放状态 |
| | | rtmpUrl: rtmpUrl, // RTMP流地址 |
| | | videoUrl4PcLive: item.videoUrl4PcLive, // 原始PC播放地址 |
| | | videoUrl4Security: item.videoUrl4Security, |
| | | videoUrl4Simple: item.videoUrl4Simple, |
| | | videoUrl4Standard: item.videoUrl4Standard |
| | | }; |
| | | }); |
| | | |
| | | this.setData({ |
| | | cameraList: cameraList, |
| | | isLoading: false |
| | | }); |
| | | |
| | | console.log('处理后的摄像头列表:', cameraList); |
| | | } else { |
| | | console.error('获取摄像头列表失败:', mockResponse.msg); |
| | | this.setData({ |
| | | isLoading: false |
| | | }); |
| | | wx.showToast({ |
| | | title: mockResponse.msg || '获取摄像头列表失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | }, 1000); // 模拟网络延迟1秒 |
| | | }, |
| | | |
| | | /** |
| | | * 播放视频 |
| | | */ |
| | | playVideo(e) { |
| | | const camera = e.currentTarget.dataset.camera; |
| | | console.log('播放摄像头:', camera.name); |
| | | |
| | | if (!camera.online) { |
| | | wx.showToast({ |
| | | title: '摄像头离线', |
| | | icon: 'error' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // 检查视频URL是否有效 |
| | | if (!camera.videoUrl4PcLive) { |
| | | wx.showToast({ |
| | | title: '视频地址无效', |
| | | icon: 'error' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | console.log('视频URL:', camera.videoUrl4PcLive); |
| | | |
| | | // 更新视频播放状态 |
| | | const cameraList = this.data.cameraList.map(item => { |
| | | if (item.id === camera.id) { |
| | | return { ...item, isPlaying: true }; |
| | | } |
| | | return item; |
| | | }); |
| | | |
| | | this.setData({ |
| | | cameraList: cameraList |
| | | }); |
| | | |
| | | // 延迟一下让live-player组件更新 |
| | | setTimeout(() => { |
| | | console.log('开始播放直播:', camera.videoUrl4PcLive); |
| | | }, 100); |
| | | }, |
| | | |
| | | /** |
| | | * 暂停视频 |
| | | */ |
| | | pauseVideo(e) { |
| | | const camera = e.currentTarget.dataset.camera; |
| | | console.log('暂停摄像头:', camera.name); |
| | | |
| | | // 更新视频播放状态 |
| | | const cameraList = this.data.cameraList.map(item => { |
| | | if (item.id === camera.id) { |
| | | return { ...item, isPlaying: false }; |
| | | } |
| | | return item; |
| | | }); |
| | | |
| | | this.setData({ |
| | | cameraList: cameraList |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 停止视频 |
| | | */ |
| | | stopVideo(e) { |
| | | const camera = e.currentTarget.dataset.camera; |
| | | console.log('停止摄像头:', camera.name); |
| | | |
| | | // 更新视频播放状态 |
| | | const cameraList = this.data.cameraList.map(item => { |
| | | if (item.id === camera.id) { |
| | | return { ...item, isPlaying: false }; |
| | | } |
| | | return item; |
| | | }); |
| | | |
| | | this.setData({ |
| | | cameraList: cameraList |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 测试视频URL |
| | | */ |
| | | testVideoUrl(e) { |
| | | const camera = e.currentTarget.dataset.camera; |
| | | console.log('测试视频URL:', camera.name); |
| | | console.log('原始URL:', camera.videoUrl4PcLive); |
| | | console.log('RTMP URL:', camera.rtmpUrl); |
| | | |
| | | // 显示URL信息 |
| | | wx.showModal({ |
| | | title: '视频URL信息', |
| | | content: `摄像头: ${camera.name}\n原始URL: ${camera.videoUrl4PcLive}\nRTMP URL: ${camera.rtmpUrl}`, |
| | | showCancel: false, |
| | | confirmText: '确定' |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 直播播放器状态变化 |
| | | */ |
| | | onLivePlayerStateChange(e) { |
| | | const camera = e.currentTarget.dataset.camera; |
| | | console.log('直播播放器状态变化:', camera.name, e.detail); |
| | | |
| | | const { code } = e.detail; |
| | | |
| | | // 显示状态信息给用户 |
| | | let statusText = ''; |
| | | let isPlaying = false; |
| | | |
| | | switch (code) { |
| | | case 2001: |
| | | statusText = '已经连接服务器'; |
| | | break; |
| | | case 2002: |
| | | statusText = '已经连接 RTMP 服务器,开始拉流'; |
| | | isPlaying = true; |
| | | break; |
| | | case 2003: |
| | | statusText = '网络接收到首个视频数据包(IDR)'; |
| | | isPlaying = true; |
| | | break; |
| | | case 2004: |
| | | statusText = '视频播放开始'; |
| | | isPlaying = true; |
| | | break; |
| | | case 2005: |
| | | statusText = '视频播放进度'; |
| | | isPlaying = true; |
| | | break; |
| | | case 2006: |
| | | statusText = '视频播放结束'; |
| | | isPlaying = false; |
| | | break; |
| | | case 2007: |
| | | statusText = '视频播放Loading'; |
| | | isPlaying = true; |
| | | break; |
| | | case 2008: |
| | | statusText = '解码器启动'; |
| | | isPlaying = true; |
| | | break; |
| | | case 2009: |
| | | statusText = '视频分辨率改变'; |
| | | isPlaying = true; |
| | | break; |
| | | case 2101: |
| | | statusText = '网络断连,且经多次重连抢救无效'; |
| | | isPlaying = false; |
| | | break; |
| | | case 2102: |
| | | statusText = '获取加速拉流地址失败'; |
| | | isPlaying = false; |
| | | break; |
| | | case 2103: |
| | | statusText = '当前视频帧解码失败'; |
| | | isPlaying = false; |
| | | break; |
| | | case 2104: |
| | | statusText = '网络断连, 已启动自动重连'; |
| | | isPlaying = false; |
| | | break; |
| | | case 2105: |
| | | statusText = '网络来断连, 且经多次重连抢救无效'; |
| | | isPlaying = false; |
| | | break; |
| | | case 2106: |
| | | statusText = '网络来断连, 且经多次重连抢救无效'; |
| | | isPlaying = false; |
| | | break; |
| | | default: |
| | | statusText = `未知状态码: ${code}`; |
| | | break; |
| | | } |
| | | |
| | | console.log(`摄像头 ${camera.name} 状态: ${statusText}`); |
| | | |
| | | // 更新播放状态 |
| | | const cameraList = this.data.cameraList.map(item => { |
| | | if (item.id === camera.id) { |
| | | return { ...item, isPlaying: isPlaying }; |
| | | } |
| | | return item; |
| | | }); |
| | | |
| | | this.setData({ |
| | | cameraList: cameraList |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 直播播放器网络状态 |
| | | */ |
| | | onLivePlayerNetStatus(e) { |
| | | const camera = e.currentTarget.dataset.camera; |
| | | console.log('直播播放器网络状态:', camera.name, e.detail); |
| | | }, |
| | | |
| | | /** |
| | | * 直播播放器错误 |
| | | */ |
| | | onLivePlayerError(e) { |
| | | const camera = e.currentTarget.dataset.camera; |
| | | console.error('直播播放器错误:', camera.name, e.detail); |
| | | |
| | | wx.showToast({ |
| | | title: '直播播放失败', |
| | | icon: 'error' |
| | | }); |
| | | |
| | | // 更新播放状态 |
| | | const cameraList = this.data.cameraList.map(item => { |
| | | if (item.id === camera.id) { |
| | | return { ...item, isPlaying: false }; |
| | | } |
| | | return item; |
| | | }); |
| | | |
| | | this.setData({ |
| | | cameraList: cameraList |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 全屏播放视频 |
| | | */ |
| | | fullscreenVideo(e) { |
| | | const camera = e.currentTarget.dataset.camera; |
| | | console.log('全屏播放:', camera.name); |
| | | |
| | | if (!camera.online) { |
| | | wx.showToast({ |
| | | title: '摄像头离线', |
| | | icon: 'error' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // 使用PC直播URL进行全屏播放 |
| | | if (camera.videoUrl4PcLive) { |
| | | console.log('全屏视频URL:', camera.videoUrl4PcLive); |
| | | |
| | | wx.showModal({ |
| | | title: '全屏播放', |
| | | content: `即将全屏播放 ${camera.name} 的视频流`, |
| | | confirmText: '开始播放', |
| | | success: (res) => { |
| | | if (res.confirm) { |
| | | // 这里可以跳转到全屏视频播放页面 |
| | | wx.showToast({ |
| | | title: '正在加载全屏视频...', |
| | | icon: 'loading' |
| | | }); |
| | | |
| | | // 模拟全屏视频加载 |
| | | setTimeout(() => { |
| | | wx.showToast({ |
| | | title: '全屏播放中', |
| | | icon: 'success' |
| | | }); |
| | | }, 1500); |
| | | } |
| | | // 由于现在直接使用RTMP URL,不需要再调用萤石云API获取播放地址 |
| | | // this.batchGetHlsUrls(cameraList); |
| | | } else { |
| | | console.error('获取摄像头列表失败:', response.msg); |
| | | this.setData({ |
| | | isLoading: false |
| | | }); |
| | | wx.showToast({ |
| | | title: response.msg || '获取摄像头列表失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error('调用接口失败:', error); |
| | | this.setData({ |
| | | isLoading: false |
| | | }); |
| | | }); |
| | | }, |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 获取气象站列表(兼容性方法,现在调用统一接口) |
| | | */ |
| | | getWeatherStationList() { |
| | | console.log('获取气象站列表(调用统一接口)'); |
| | | this.getAllDeviceInfo(); |
| | | }, |
| | | |
| | | /** |
| | | * 选择气象站 |
| | | */ |
| | | selectWeatherStation(index) { |
| | | const weatherStation = this.data.weatherStationList[index]; |
| | | if (!weatherStation) return; |
| | | |
| | | console.log('选择气象站:', weatherStation.name); |
| | | |
| | | // 获取该气象站的详细数据 |
| | | this.getWeatherStationData(weatherStation.id); |
| | | |
| | | this.setData({ |
| | | selectedWeatherStationIndex: index |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 获取气象站详细数据 |
| | | */ |
| | | getWeatherStationData(stationId) { |
| | | console.log('获取气象站数据:', stationId); |
| | | |
| | | // 调用真实接口获取气象站详细信息 |
| | | this.getWeatherLastData(stationId); |
| | | }, |
| | | |
| | | /** |
| | | * 调用 /wx/mqttLast/oneWeatherLast 接口获取气象站详细信息 |
| | | */ |
| | | getWeatherLastData(weatherId) { |
| | | console.log('开始调用 /wx/mqttLast/oneWeatherLast 接口获取气象站详细信息'); |
| | | console.log('气象站ID:', weatherId); |
| | | |
| | | get({url: `/wx/mqttLast/oneWeatherLast?weatherId=${weatherId}`}) |
| | | .then(response => { |
| | | console.log('气象站详细信息接口返回数据:', response); |
| | | |
| | | if (response.success && response.code === '0001') { |
| | | const content = response.content; |
| | | |
| | | // 处理接口返回的气象站数据 |
| | | const weatherData = { |
| | | id: content.id, |
| | | weatherId: content.weatherId, |
| | | weatherName: content.weatherName || '气象站', |
| | | dt: content.dt, |
| | | // 气象数据 |
| | | temperature: content.airTemperature, // 空气温度 |
| | | humidity: content.airHumidity, // 空气湿度 |
| | | uv: content.ultraviolet, // 紫外线 |
| | | light: content.lightIntensity, // 光照强度 |
| | | rainfall: content.rainfall, // 雨量 |
| | | windSpeed: content.windSpeed, // 风速 |
| | | windDirection: content.windDirectionStr, // 风向描述 |
| | | windDirectionAngle: content.windDirection, // 风向角度 |
| | | // 在线状态 |
| | | onLine: content.onLine, |
| | | // 格式化显示数据 |
| | | lastUpdate: content.dt || new Date().toLocaleString() |
| | | }; |
| | | |
| | | this.setData({ |
| | | currentWeatherStation: weatherData |
| | | }); |
| | | |
| | | console.log('处理后的气象站数据:', weatherData); |
| | | |
| | | } else { |
| | | console.error('获取气象站详细信息失败:', response.msg); |
| | | wx.showToast({ |
| | | title: response.msg || '获取气象站详细信息失败', |
| | | icon: 'none' |
| | | }); |
| | | |
| | | // 如果接口调用失败,使用模拟数据作为备选 |
| | | this.setMockWeatherData(stationId); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error('调用气象站详细信息接口失败:', error); |
| | | wx.showToast({ |
| | | title: '获取气象站详细信息失败', |
| | | icon: 'error' |
| | | }); |
| | | |
| | | // 如果接口调用失败,使用模拟数据作为备选 |
| | | this.setMockWeatherData(stationId); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 设置模拟气象站数据(作为接口调用失败的备选方案) |
| | | */ |
| | | setMockWeatherData(stationId) { |
| | | console.log('使用模拟气象站数据:', stationId); |
| | | |
| | | const mockWeatherData = { |
| | | id: stationId, |
| | | weatherId: stationId, |
| | | weatherName: '气象站', |
| | | dt: new Date().toLocaleString(), |
| | | temperature: 0.0, |
| | | humidity: 0.0, |
| | | uv: 0, |
| | | light: 0, |
| | | rainfall: 0.00, |
| | | windSpeed: 0.00, |
| | | windDirection: '北', |
| | | windDirectionAngle: 0, |
| | | onLine: false, |
| | | online: true, |
| | | lastUpdate: new Date().toLocaleString() |
| | | }; |
| | | |
| | | this.setData({ |
| | | currentWeatherStation: mockWeatherData |
| | | }); |
| | | }, |
| | | |
| | | |
| | | |
| | | /** |
| | | * 气象站选择改变 |
| | | */ |
| | | onWeatherStationChange(e) { |
| | | const index = e.detail.value; |
| | | this.selectWeatherStation(index); |
| | | }, |
| | | |
| | | /** |
| | | * 刷新气象数据 |
| | | */ |
| | | refreshWeatherData() { |
| | | if (!this.data.currentWeatherStation) { |
| | | wx.showToast({ |
| | | title: '请先选择气象站', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | console.log('刷新气象数据'); |
| | | |
| | | wx.showLoading({ |
| | | title: '刷新中...' |
| | | }); |
| | | |
| | | // 重新调用接口获取最新数据 |
| | | this.getWeatherLastData(this.data.currentWeatherStation.weatherId || this.data.currentWeatherStation.id); |
| | | |
| | | wx.hideLoading(); |
| | | wx.showToast({ |
| | | title: '刷新成功', |
| | | icon: 'success' |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 选择土壤墒情站 |
| | | */ |
| | | selectSoilStation(index) { |
| | | const soilStation = this.data.soilStationList[index]; |
| | | if (!soilStation) return; |
| | | |
| | | console.log('选择土壤墒情站:', soilStation.name); |
| | | |
| | | // 获取该土壤墒情站的详细数据 |
| | | this.getSoilStationData(soilStation.id); |
| | | |
| | | this.setData({ |
| | | selectedSoilStationIndex: index |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 获取土壤墒情站详细数据 |
| | | */ |
| | | getSoilStationData(stationId) { |
| | | console.log('获取土壤墒情站数据:', stationId); |
| | | |
| | | // 调用真实接口获取土壤墒情站详细信息 |
| | | this.getSoilLastData(stationId); |
| | | }, |
| | | |
| | | /** |
| | | * 调用 /wx/mqttLast/oneSoilLast 接口获取土壤墒情站详细信息 |
| | | */ |
| | | getSoilLastData(soilId) { |
| | | console.log('开始调用 /wx/mqttLast/oneSoilLast 接口获取土壤墒情站详细信息'); |
| | | console.log('土壤墒情站ID:', soilId); |
| | | |
| | | get({url: `/wx/mqttLast/oneSoilLast?soilId=${soilId}`}) |
| | | .then(response => { |
| | | console.log('土壤墒情站详细信息接口返回数据:', response); |
| | | |
| | | if (response.success && response.code === '0001') { |
| | | const content = response.content; |
| | | |
| | | // 处理接口返回的土壤墒情站数据 |
| | | const soilData = { |
| | | id: content.id, |
| | | soilId: content.soilId, |
| | | soilName: content.soilName || '土壤墒情站', |
| | | dt: content.dt, |
| | | // 5层土壤湿度数据 |
| | | soilHumidity1: content.soilHumidity1, |
| | | soilHumidity2: content.soilHumidity2, |
| | | soilHumidity3: content.soilHumidity3, |
| | | soilHumidity4: content.soilHumidity4, |
| | | soilHumidity5: content.soilHumidity5, |
| | | // 5层土壤温度数据 |
| | | soilTemperature1: content.soilTemperature1, |
| | | soilTemperature2: content.soilTemperature2, |
| | | soilTemperature3: content.soilTemperature3, |
| | | soilTemperature4: content.soilTemperature4, |
| | | soilTemperature5: content.soilTemperature5, |
| | | // 在线状态 |
| | | onLine: content.onLine, |
| | | // 计算在线状态 |
| | | online: content.onLine === 1, |
| | | // 格式化显示数据 |
| | | lastUpdate: content.dt || new Date().toLocaleString() |
| | | }; |
| | | |
| | | this.setData({ |
| | | currentSoilStation: soilData |
| | | }); |
| | | |
| | | console.log('处理后的土壤墒情站数据:', soilData); |
| | | |
| | | } else { |
| | | console.error('获取土壤墒情站详细信息失败:', response.msg); |
| | | wx.showToast({ |
| | | title: response.msg || '获取土壤墒情站详细信息失败', |
| | | icon: 'none' |
| | | }); |
| | | |
| | | // 如果接口调用失败,使用模拟数据作为备选 |
| | | this.setMockSoilData(stationId); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error('调用土壤墒情站详细信息接口失败:', error); |
| | | wx.showToast({ |
| | | title: '获取土壤墒情站详细信息失败', |
| | | icon: 'error' |
| | | }); |
| | | |
| | | // 如果接口调用失败,使用模拟数据作为备选 |
| | | this.setMockSoilData(stationId); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 设置模拟土壤墒情站数据(作为接口调用失败的备选方案) |
| | | */ |
| | | setMockSoilData(stationId) { |
| | | console.log('使用模拟土壤墒情站数据:', stationId); |
| | | |
| | | const mockSoilData = { |
| | | id: stationId, |
| | | soilId: stationId, |
| | | soilName: '土壤墒情站', |
| | | dt: new Date().toLocaleString(), |
| | | // 5层土壤湿度数据 |
| | | soilHumidity1: 0.00, |
| | | soilHumidity2: 0.00, |
| | | soilHumidity3: 0.00, |
| | | soilHumidity4: 0.00, |
| | | soilHumidity5: 0.00, |
| | | // 5层土壤温度数据 |
| | | soilTemperature1: 0.00, |
| | | soilTemperature2: 0.00, |
| | | soilTemperature3: 0.00, |
| | | soilTemperature4: 0.00, |
| | | soilTemperature5: 0.00, |
| | | // 在线状态 |
| | | onLine: false, |
| | | lastUpdate: new Date().toLocaleString() |
| | | }; |
| | | |
| | | this.setData({ |
| | | currentSoilStation: mockSoilData |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 土壤墒情站选择改变 |
| | | */ |
| | | onSoilStationChange(e) { |
| | | const index = e.detail.value; |
| | | this.selectSoilStation(index); |
| | | }, |
| | | |
| | | /** |
| | | * 刷新土壤墒情数据 |
| | | */ |
| | | refreshSoilData() { |
| | | if (!this.data.currentSoilStation) { |
| | | wx.showToast({ |
| | | title: '请先选择土壤墒情站', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | console.log('刷新土壤墒情数据'); |
| | | |
| | | wx.showLoading({ |
| | | title: '刷新中...' |
| | | }); |
| | | |
| | | // 重新调用接口获取最新数据 |
| | | this.getSoilLastData(this.data.currentSoilStation.soilId || this.data.currentSoilStation.id); |
| | | |
| | | wx.hideLoading(); |
| | | wx.showToast({ |
| | | title: '刷新成功', |
| | | icon: 'success' |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 获取水肥机列表(兼容性方法,现在调用统一接口) |
| | | */ |
| | | getFertilizerStationList() { |
| | | console.log('获取水肥机列表(调用统一接口)'); |
| | | this.getAllDeviceInfo(); |
| | | }, |
| | | |
| | | /** |
| | | * 选择水肥机 |
| | | */ |
| | | selectFertilizerStation(index) { |
| | | const fertilizerStation = this.data.fertilizerStationList[index]; |
| | | if (!fertilizerStation) return; |
| | | |
| | | console.log('选择水肥机:', fertilizerStation.name); |
| | | |
| | | // 获取该水肥机的详细数据 |
| | | this.getFertilizerStationData(fertilizerStation.id); |
| | | |
| | | this.setData({ |
| | | selectedFertilizerStationIndex: index |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 获取水肥机详细数据 |
| | | */ |
| | | getFertilizerStationData(stationId) { |
| | | console.log('获取水肥机数据:', stationId); |
| | | |
| | | // 调用真实接口获取水肥机详细信息 |
| | | this.getManureLastData(stationId); |
| | | }, |
| | | |
| | | /** |
| | | * 调用 /wx/mqttLast/oneManureLast 接口获取水肥机详细信息 |
| | | */ |
| | | getManureLastData(manureId) { |
| | | console.log('开始调用 /wx/mqttLast/oneManureLast 接口获取水肥机详细信息'); |
| | | console.log('水肥机ID:', manureId); |
| | | |
| | | get({url: `/wx/mqttLast/oneManureLast?manureId=${manureId}`}) |
| | | .then(response => { |
| | | console.log('水肥机详细信息接口返回数据:', response); |
| | | |
| | | if (response.success && response.code === '0001') { |
| | | const content = response.content; |
| | | |
| | | // 处理接口返回的水肥机数据 |
| | | const fertilizerData = { |
| | | id: content.id, |
| | | manureId: content.manureId, |
| | | manureName: content.manureName || '水肥机', |
| | | dt: content.dt, |
| | | alarm: content.alarm, |
| | | // 搅拌运行状态 |
| | | stirRunning1: content.stirRunning1, |
| | | // 注肥运行状态 |
| | | injectRunning: content.injectRunning, |
| | | // 流量和时间数据 |
| | | manureFlow: content.manureFlow, |
| | | manureTime: content.manureTime, |
| | | stirTime: content.stirTime, |
| | | stirDuration: content.stirDuration, |
| | | injectDuration: content.injectDuration, |
| | | // 在线状态 |
| | | onLine: content.onLine, |
| | | // 计算运行状态 |
| | | mixingEnabled: content.stirRunning1 === 1, |
| | | fertilizingEnabled: content.injectRunning === 1, |
| | | // 格式化显示数据 |
| | | lastUpdate: content.dt || new Date().toLocaleString() |
| | | }; |
| | | |
| | | this.setData({ |
| | | currentFertilizerStation: fertilizerData |
| | | }); |
| | | |
| | | console.log('处理后的水肥机数据:', fertilizerData); |
| | | |
| | | } else { |
| | | console.error('获取水肥机详细信息失败:', response.msg); |
| | | wx.showToast({ |
| | | title: response.msg || '获取水肥机详细信息失败', |
| | | icon: 'none' |
| | | }); |
| | | |
| | | // 如果接口调用失败,使用模拟数据作为备选 |
| | | this.setMockFertilizerData(stationId); |
| | | } |
| | | }) |
| | | .catch(error => { |
| | | console.error('调用水肥机详细信息接口失败:', error); |
| | | wx.showToast({ |
| | | title: '获取水肥机详细信息失败', |
| | | icon: 'error' |
| | | }); |
| | | |
| | | // 如果接口调用失败,使用模拟数据作为备选 |
| | | this.setMockFertilizerData(stationId); |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 设置模拟水肥机数据(作为接口调用失败的备选方案) |
| | | */ |
| | | setMockFertilizerData(stationId) { |
| | | console.log('使用模拟水肥机数据:', stationId); |
| | | |
| | | const mockFertilizerData = { |
| | | id: stationId, |
| | | manureId: stationId, |
| | | manureName: '水肥机', |
| | | dt: new Date().toLocaleString(), |
| | | alarm: 0, |
| | | stirRunning1: 0, |
| | | injectRunning: 0, |
| | | manureFlow: 0.00, |
| | | manureTime: 0, |
| | | stirTime: 0, |
| | | stirDuration: 300, |
| | | injectDuration: 300, |
| | | onLine: false, |
| | | mixingEnabled: false, |
| | | fertilizingEnabled: false, |
| | | lastUpdate: new Date().toLocaleString() |
| | | }; |
| | | |
| | | this.setData({ |
| | | currentFertilizerStation: mockFertilizerData |
| | | }); |
| | | }, |
| | | |
| | | |
| | | |
| | | /** |
| | | * 水肥机选择改变 |
| | | */ |
| | | onFertilizerStationChange(e) { |
| | | const index = e.detail.value; |
| | | this.selectFertilizerStation(index); |
| | | }, |
| | | |
| | | /** |
| | | * 刷新水肥机数据 |
| | | */ |
| | | refreshFertilizerData() { |
| | | if (!this.data.currentFertilizerStation) { |
| | | wx.showToast({ |
| | | title: '请先选择水肥机', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | console.log('刷新水肥机数据'); |
| | | |
| | | wx.showLoading({ |
| | | title: '刷新中...' |
| | | }); |
| | | |
| | | // 重新调用接口获取最新数据 |
| | | this.getManureLastData(this.data.currentFertilizerStation.manureId || this.data.currentFertilizerStation.id); |
| | | |
| | | wx.hideLoading(); |
| | | wx.showToast({ |
| | | title: '刷新成功', |
| | | icon: 'success' |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 切换搅拌开关 |
| | | */ |
| | | toggleMixing(e) { |
| | | const enabled = e.detail.value; |
| | | console.log('搅拌开关:', enabled ? '开启' : '关闭'); |
| | | |
| | | if (!this.data.currentFertilizerStation) return; |
| | | |
| | | // 更新搅拌状态 |
| | | const currentStation = { |
| | | ...this.data.currentFertilizerStation |
| | | }; |
| | | currentStation.mixingEnabled = enabled; |
| | | |
| | | // 更新具体的搅拌运行状态(这里假设只控制第一个搅拌器) |
| | | currentStation.stirRunning1 = enabled ? 1 : 0; |
| | | |
| | | this.setData({ |
| | | currentFertilizerStation: currentStation |
| | | }); |
| | | |
| | | // 显示操作结果 |
| | | wx.showToast({ |
| | | title: enabled ? '搅拌已开启' : '搅拌已关闭', |
| | | icon: 'success' |
| | | }); |
| | | }, |
| | | |
| | | /** |
| | | * 切换注肥开关 |
| | | */ |
| | | toggleFertilizing(e) { |
| | | const enabled = e.detail.value; |
| | | console.log('注肥开关:', enabled ? '开启' : '关闭'); |
| | | |
| | | if (!this.data.currentFertilizerStation) return; |
| | | |
| | | // 更新注肥状态 |
| | | const currentStation = { |
| | | ...this.data.currentFertilizerStation |
| | | }; |
| | | currentStation.fertilizingEnabled = enabled; |
| | | |
| | | // 更新注肥运行状态 |
| | | currentStation.injectRunning = enabled ? 1 : 0; |
| | | |
| | | this.setData({ |
| | | currentFertilizerStation: currentStation |
| | | }); |
| | | |
| | | // 显示操作结果 |
| | | wx.showToast({ |
| | | title: enabled ? '注肥已开启' : '注肥已关闭', |
| | | icon: 'success' |
| | | }); |
| | | }, |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 手动重试获取播放地址 |
| | | */ |
| | | retryGetHlsUrl(e) { |
| | | const camera = e.currentTarget.dataset.camera; |
| | | if (!camera) { |
| | | console.error('重试失败:摄像头信息不完整'); |
| | | wx.showToast({ |
| | | title: '摄像头信息不完整', |
| | | icon: 'error' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | console.log('=== 手动重试获取播放地址 ==='); |
| | | console.log(`摄像头: ${camera.name}, ID: ${camera.id}`); |
| | | console.log('当前状态:', { |
| | | online: camera.online, |
| | | hslUrl: camera.hslUrl, |
| | | isLoadingUrl: camera.isLoadingUrl, |
| | | urlError: camera.urlError |
| | | }); |
| | | |
| | | // 重置错误状态并重新获取 |
| | | this.updateCameraUrlLoadingState(camera.id, false, false); |
| | | this.getHlsUrlForCamera(camera); |
| | | }, |
| | | |
| | | /** |
| | | * 更新摄像头URL加载状态 |
| | | */ |
| | | updateCameraUrlLoadingState(cameraId, isLoading, hasError) { |
| | | console.log('=== 更新摄像头URL加载状态 ==='); |
| | | console.log('参数:', { cameraId, isLoading, hasError }); |
| | | |
| | | const cameraList = this.data.cameraList.map(item => { |
| | | if (item.id === cameraId) { |
| | | const updatedItem = { |
| | | ...item, |
| | | isLoadingUrl: isLoading, |
| | | urlError: hasError |
| | | }; |
| | | console.log(`摄像头 ${cameraId} 状态更新:`, { |
| | | name: updatedItem.name, |
| | | isLoadingUrl: updatedItem.isLoadingUrl, |
| | | urlError: updatedItem.urlError |
| | | }); |
| | | return updatedItem; |
| | | } |
| | | return item; |
| | | }); |
| | | |
| | | this.setData({ |
| | | cameraList: cameraList |
| | | }); |
| | | |
| | | console.log('状态更新完成,当前摄像头列表:', cameraList); |
| | | }, |
| | | |
| | | /** |
| | | * 为单个摄像头获取HLS播放地址 |
| | | */ |
| | | getHlsUrlForCamera(camera) { |
| | | if (!camera || !camera.deviceSerial) { |
| | | console.error('摄像头信息不完整:', camera); |
| | | return; |
| | | } |
| | | |
| | | console.log('=== 获取播放地址开始 ==='); |
| | | console.log(`摄像头: ${camera.name}, ID: ${camera.id}, 设备序列号: ${camera.deviceSerial}`); |
| | | console.log('当前accessToken:', this.data.accessToken); |
| | | |
| | | // 更新加载状态 |
| | | this.updateCameraUrlLoadingState(camera.id, true, false); |
| | | |
| | | // 调用萤石云API获取播放地址 |
| | | this.getHlsUrl(this.data.accessToken, camera.deviceSerial, camera.id); |
| | | }, |
| | | |
| | | /** |
| | | * ezplayer错误处理 |
| | | */ |
| | | handleError(e) { |
| | | console.log('=== ezplayer 错误处理 ==='); |
| | | console.log('错误事件详情:', e); |
| | | console.log('错误详情:', e.detail); |
| | | |
| | | // 获取摄像头信息 |
| | | const cameraId = e.currentTarget.id; |
| | | console.log('出错的摄像头ID:', cameraId); |
| | | |
| | | // 查找对应的摄像头 |
| | | const camera = this.data.cameraList.find(item => `ezplayer-${item.id}` === cameraId); |
| | | if (camera) { |
| | | console.log('出错的摄像头信息:', camera); |
| | | |
| | | // 更新错误状态 |
| | | this.updateCameraUrlLoadingState(camera.id, false, true); |
| | | |
| | | // 显示错误提示 |
| | | wx.showToast({ |
| | | title: '视频播放出错', |
| | | icon: 'error', |
| | | duration: 2000 |
| | | }); |
| | | } else { |
| | | wx.showToast({ |
| | | title: '全屏视频地址无效', |
| | | icon: 'error' |
| | | }); |
| | | console.error('未找到对应的摄像头:', cameraId); |
| | | } |
| | | }, |
| | | |
| | | /** |
| | | * 摄像头设置 |
| | | * ezplayer控制事件 |
| | | */ |
| | | cameraSettings(e) { |
| | | const camera = e.currentTarget.dataset.camera; |
| | | console.log('摄像头设置:', camera.name); |
| | | onControlEvent(e) { |
| | | console.log('=== ezplayer 控制事件 ==='); |
| | | console.log('控制事件详情:', e); |
| | | console.log('事件类型:', e.type); |
| | | console.log('事件数据:', e.detail); |
| | | |
| | | wx.showActionSheet({ |
| | | itemList: ['云台控制', '录像设置', '画质调节', '报警设置'], |
| | | success: (res) => { |
| | | const actions = ['云台控制', '录像设置', '画质调节', '报警设置']; |
| | | wx.showToast({ |
| | | title: `${actions[res.tapIndex]}功能开发中`, |
| | | icon: 'none' |
| | | }); |
| | | // 获取摄像头信息 |
| | | const cameraId = e.currentTarget.id; |
| | | console.log('事件来源摄像头ID:', cameraId); |
| | | |
| | | // 查找对应的摄像头 |
| | | const camera = this.data.cameraList.find(item => `ezplayer-${item.id}` === cameraId); |
| | | if (camera) { |
| | | console.log('事件来源摄像头信息:', camera); |
| | | |
| | | // 根据事件类型处理 |
| | | switch (e.type) { |
| | | case 'play': |
| | | console.log('视频开始播放'); |
| | | |
| | | break; |
| | | case 'pause': |
| | | console.log('视频暂停播放'); |
| | | |
| | | break; |
| | | case 'ended': |
| | | console.log('视频播放结束'); |
| | | |
| | | break; |
| | | case 'error': |
| | | console.log('视频播放错误'); |
| | | this.updateCameraUrlLoadingState(camera.id, false, true); |
| | | break; |
| | | default: |
| | | console.log('未知事件类型:', e.type); |
| | | } |
| | | } else { |
| | | console.error('未找到对应的摄像头:', cameraId); |
| | | } |
| | | }, |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 更新摄像头播放状态 |
| | | */ |
| | | updateCameraPlayState(cameraId, isPlaying) { |
| | | console.log('=== 更新摄像头播放状态 ==='); |
| | | console.log('参数:', { cameraId, isPlaying }); |
| | | |
| | | const cameraList = this.data.cameraList.map(item => { |
| | | if (item.id === cameraId) { |
| | | const updatedItem = { |
| | | ...item, |
| | | isPlaying: isPlaying |
| | | }; |
| | | console.log(`摄像头 ${cameraId} 播放状态更新:`, { |
| | | name: updatedItem.name, |
| | | isPlaying: updatedItem.isPlaying |
| | | }); |
| | | return updatedItem; |
| | | } |
| | | return item; |
| | | }); |
| | | } |
| | | }) |
| | | |
| | | this.setData({ |
| | | cameraList: cameraList |
| | | }); |
| | | |
| | | console.log('播放状态更新完成'); |
| | | }, |
| | | |
| | | |
| | | }) |