当前位置: 首页 > ops >正文

微信小程序对接EdgeX Foundry详细指南

微信小程序对接EdgeX Foundry详细指南

系统架构概述

微信小程序 → 服务器API网关/反向代理 → EdgeX Foundry (部署在服务器)

由于微信小程序要求所有请求必须使用HTTPS且域名需要备案,小程序无法直接访问EdgeX的API,需要通过服务器端做中转或反向代理。

第一部分:服务器端配置

方法一:使用Nginx反向代理(推荐)

  1. 安装Nginx

    # Ubuntu/Debian
    sudo apt update && sudo apt install nginx# CentOS/RHEL
    sudo yum install epel-release && sudo yum install nginx
    
  2. 配置Nginx反向代理
    创建配置文件 /etc/nginx/conf.d/edgex.conf

    server {listen 443 ssl;server_name your-domain.com; # 替换为已备案的域名# SSL证书配置ssl_certificate /path/to/your/certificate.crt;ssl_certificate_key /path/to/your/private.key;# 核心数据API代理location /edgex/core-data/ {proxy_pass http://localhost:59880/api/v2/;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;# 添加CORS头部add_header 'Access-Control-Allow-Origin' '*' always;add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;# 处理预检请求if ($request_method = 'OPTIONS') {add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';add_header 'Access-Control-Max-Age' 1728000;add_header 'Content-Type' 'text/plain; charset=utf-8';add_header 'Content-Length' 0;return 204;}}# 设备服务API代理location /edgex/device-service/ {proxy_pass http://localhost:59881/api/v2/;# ... 类似上面的配置}
    }
    
  3. 重启Nginx

    sudo nginx -t && sudo systemctl restart nginx
    

方法二:使用Node.js编写API网关(更灵活)

  1. 创建项目目录

    mkdir edgex-gateway && cd edgex-gateway
    npm init -y
    npm install express cors axios
    
  2. 创建网关服务器文件 gateway.js

    const express = require('express');
    const cors = require('cors');
    const axios = require('axios');
    const app = express();
    const port = 3000;// 中间件
    app.use(cors());
    app.use(express.json());// EdgeX服务地址配置
    const EDGEX_CONFIG = {coreData: 'http://localhost:59880',deviceService: 'http://localhost:59881',command: 'http://localhost:59882'
    };// 身份验证中间件(可选)
    const authenticate = (req, res, next) => {// 这里可以添加JWT验证逻辑const token = req.header('Authorization');if (!token) {return res.status(401).json({ error: '访问被拒绝,缺少令牌' });}// 验证token逻辑...next();
    };// 获取设备数据
    app.get('/api/devices/:deviceName/events', authenticate, async (req, res) => {try {const { deviceName } = req.params;const { limit = 10 } = req.query;const response = await axios.get(`${EDGEX_CONFIG.coreData}/api/v2/event/device/name/${deviceName}?limit=${limit}`);res.json({success: true,data: response.data});} catch (error) {res.status(500).json({success: false,message: '获取设备数据失败',error: error.message});}
    });// 发送命令到设备
    app.post('/api/devices/:deviceName/command', authenticate, async (req, res) => {try {const { deviceName } = req.params;const { command, params } = req.body;const response = await axios.post(`${EDGEX_CONFIG.command}/api/v2/device/name/${deviceName}/${command}`,params);res.json({success: true,data: response.data});} catch (error) {res.status(500).json({success: false,message: '发送命令失败',error: error.message});}
    });// 获取设备列表
    app.get('/api/devices', authenticate, async (req, res) => {try {const response = await axios.get(`${EDGEX_CONFIG.coreData}/api/v2/device/all?limit=100`);res.json({success: true,data: response.data});} catch (error) {res.status(500).json({success: false,message: '获取设备列表失败',error: error.message});}
    });app.listen(port, () => {console.log(`EdgeX网关服务器运行在端口 ${port}`);
    });
    
  3. 使用PM2管理进程

    npm install -g pm2
    pm2 start gateway.js --name edgex-gateway
    pm2 save
    pm2 startup
    

第二部分:微信小程序开发

1. 小程序网络请求封装

创建 utils/api.js 文件:

const BASE_URL = 'https://your-domain.com'; // 替换为您的域名class ApiClient {constructor() {this.token = wx.getStorageSync('token');}// 统一请求方法request(url, method = 'GET', data = {}) {return new Promise((resolve, reject) => {const header = {'Content-Type': 'application/json'};if (this.token) {header['Authorization'] = `Bearer ${this.token}`;}wx.request({url: BASE_URL + url,method: method,data: data,header: header,success: (res) => {if (res.statusCode === 200) {resolve(res.data);} else {reject(res.data);}},fail: (error) => {reject(error);}});});}// 获取设备事件数据getDeviceEvents(deviceName, limit = 10) {return this.request(`/api/devices/${deviceName}/events?limit=${limit}`);}// 发送设备命令sendDeviceCommand(deviceName, command, params) {return this.request(`/api/devices/${deviceName}/command`, 'POST', {command,params});}// 获取设备列表getDeviceList() {return this.request('/api/devices');}
}export default new ApiClient();

2. 小程序页面示例

创建 pages/device/device.js

const api = require('../../utils/api.js');Page({data: {deviceList: [],currentDevice: null,events: [],loading: false},onLoad() {this.loadDevices();},// 加载设备列表async loadDevices() {this.setData({ loading: true });try {const result = await api.getDeviceList();this.setData({deviceList: result.data.devices,loading: false});} catch (error) {wx.showToast({title: '加载设备失败',icon: 'none'});this.setData({ loading: false });}},// 选择设备onSelectDevice(e) {const device = e.currentTarget.dataset.device;this.setData({ currentDevice: device });this.loadDeviceEvents(device.name);},// 加载设备事件async loadDeviceEvents(deviceName) {this.setData({ loading: true });try {const result = await api.getDeviceEvents(deviceName, 20);this.setData({events: result.data.events,loading: false});} catch (error) {wx.showToast({title: '加载数据失败',icon: 'none'});this.setData({ loading: false });}},// 发送命令async sendCommand() {if (!this.data.currentDevice) {wx.showToast({title: '请先选择设备',icon: 'none'});return;}try {const result = await api.sendDeviceCommand(this.data.currentDevice.name, 'switch', { value: 'on' });wx.showToast({title: '命令发送成功',icon: 'success'});} catch (error) {wx.showToast({title: '命令发送失败',icon: 'none'});}}
});

创建 pages/device/device.wxml

<view class="container"><!-- 设备选择 --><view class="section"><text class="section-title">选择设备</text><scroll-view scroll-x class="device-scroll"><view wx:for="{{deviceList}}" wx:key="id" class="device-item {{currentDevice && currentDevice.id === item.id ? 'active' : ''}}"bindtap="onSelectDevice"data-device="{{item}}"><text>{{item.name}}</text></view></scroll-view></view><!-- 设备数据 --><view class="section" wx:if="{{currentDevice}}"><text class="section-title">设备数据: {{currentDevice.name}}</text><view class="data-card"><view class="data-item" wx:for="{{events}}" wx:key="id"><text class="data-label">{{item.readings[0].resourceName}}:</text><text class="data-value">{{item.readings[0].value}}</text><text class="data-time">{{item.origin}}</text></view></view><button type="primary" bindtap="sendCommand" loading="{{loading}}">发送开启命令</button></view><!-- 加载状态 --><view wx:if="{{loading}}" class="loading"><text>加载中...</text></view>
</view>

创建 pages/device/device.wxss

.container {padding: 20rpx;
}.section {margin-bottom: 40rpx;
}.section-title {font-size: 32rpx;font-weight: bold;display: block;margin-bottom: 20rpx;
}.device-scroll {white-space: nowrap;width: 100%;
}.device-item {display: inline-block;padding: 20rpx 40rpx;margin-right: 20rpx;background-color: #f5f5f5;border-radius: 10rpx;
}.device-item.active {background-color: #007aff;color: white;
}.data-card {background-color: #fff;border-radius: 10rpx;padding: 20rpx;margin-bottom: 20rpx;box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
}.data-item {padding: 20rpx 0;border-bottom: 1rpx solid #eee;
}.data-item:last-child {border-bottom: none;
}.data-label {font-weight: bold;margin-right: 20rpx;
}.data-value {color: #007aff;
}.data-time {display: block;font-size: 24rpx;color: #999;margin-top: 10rpx;
}.loading {text-align: center;padding: 40rpx;color: #999;
}

3. 小程序配置文件

app.json 中添加页面配置:

{"pages": ["pages/device/device"],"window": {"navigationBarTitleText": "EdgeX设备监控","navigationBarBackgroundColor": "#007aff","navigationBarTextStyle": "white"},"networkTimeout": {"request": 10000}
}

第三部分:安全增强建议

  1. API访问控制

    // 在网关服务器中添加身份验证
    const jwt = require('jsonwebtoken');// 登录接口
    app.post('/api/login', async (req, res) => {const { username, password } = req.body;// 验证用户 credentials (简化示例)if (username === 'admin' && password === 'password') {const token = jwt.sign({ userId: 1 }, 'your-secret-key', { expiresIn: '24h' });res.json({ success: true, token });} else {res.status(401).json({ success: false, message: '认证失败' });}
    });
    
  2. 请求频率限制

    const rateLimit = require('express-rate-limit');const limiter = rateLimit({windowMs: 15 * 60 * 1000, // 15分钟max: 100 // 限制每个IP每15分钟最多100次请求
    });app.use('/api/', limiter);
    

部署和测试步骤

  1. 部署EdgeX Foundry到您的服务器
  2. 配置Nginx反向代理或部署Node.js网关
  3. 申请HTTPS证书并配置到Nginx
  4. 微信小程序后台配置服务器域名
  5. 开发并上传小程序
  6. 测试设备数据读取和命令发送

常见问题解决

  1. 跨域问题:确保Nginx配置了正确的CORS头
  2. HTTPS问题:小程序要求所有请求使用HTTPS
  3. 域名备案:小程序要求的域名必须已完成ICP备案
  4. API限制:微信小程序有网络请求API的调用频率限制

这个方案提供了从服务器配置到小程序开发的完整实现,可以根据实际需求进行调整和扩展。

http://www.xdnf.cn/news/18914.html

相关文章:

  • 云计算学习100天-第31天
  • 从零开始的云计算生活——第五十三天,发愤图强,kubernetes模块之Prometheus和发布
  • 【SpringAI】快速上手,详解项目快速集成主流大模型DeepSeek,ChatGPT
  • 【TEC045-KIT】基于复旦微 FMQL45T900 的全国产化 ARM 开发套件
  • Uniapp中自定义导航栏
  • 如何将iPhone上的隐藏照片传输到电脑
  • Flask测试平台开发实战-第二篇
  • 服务器核心组件:CPU 与 GPU 的核心区别、应用场景、协同工作
  • 麒麟操作系统挂载NAS服务器
  • React中优雅管理CSS变量的最佳实践
  • 【动态规划】子数组、子串问题
  • 保姆级教程 | 在Ubuntu上部署Claude Code Plan Mode全过程
  • 设计模式相关面试题
  • 2025年KBS SCI1区TOP,矩阵差分进化算法+移动网络视觉覆盖无人机轨迹优化,深度解析+性能实测
  • 前端异常监控,性能监控,埋点,怎么做的
  • Android 开发 - 数据共享(数据共享、内容提供者实现、动态权限申请)
  • 深度学习篇---模型参数保存
  • [肥用云计算] Serverless 多环境配置
  • PCM转音频
  • 面试之HashMap
  • LightRAG
  • 文档格式转换软件 一键Word转PDF
  • PPT处理控件Aspose.Slides教程:在 C# 中将 PPTX 转换为 Markdown
  • 【qml-7】qml与c++交互(自动补全提示)
  • [n8n] 全文检索(FTS)集成 | Mermaid图表生成
  • Android 使用MediaMuxer+MediaCodec编码MP4视频
  • 辅助驾驶出海、具身智能落地,稀缺的3D数据从哪里来?
  • 介绍智慧城管十大核心功能之一:风险预警系统
  • 架构评审:构建稳定、高效、可扩展的技术架构(下)
  • Java8-21的核心特性以及用法