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

微信小程序对接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.dtcms.com/a/354725.html

相关文章:

  • 导入文件允许合并表格
  • 上海控安:汽车API安全-风险与防护策略解析
  • Elasticsearch数据迁移方案深度对比:三种方法的优劣分析
  • 领悟8种常见的设计模式
  • 74HC595芯片简析
  • OpenCV 基础操作实战指南:从图像处理到交互控制
  • Ubuntu有限网口无法使用解决方法
  • 企业级AI应用场景的核心特征
  • Fluent Bit针对kafka心跳重连机制详解(上)
  • DA14531(Cortex-M0+)之Wake-up Interrupt Controller (WIC)
  • JumpServer开源堡垒机:统一访问入口 + 安全管控 + 操作审计
  • 从0开始搭建一个前端项目(vue + vite + typescript)
  • 第6篇:链路追踪系统 - 分布式环境下的请求跟踪
  • 【STM32】G030单片机的窗口看门狗
  • 从协作机器人到智能协作机器人:工业革命的下一跳
  • Fluent Bit针对kafka心跳重连机制详解(下)
  • KubeBlocks For MySQL 云原生设计分享
  • Logstash数据迁移之mysql-to-kafka.conf详细配置
  • 卷积神经网络(CNN)搭建详解
  • 区块链+隐私计算护航“东数西算”数据安全报告
  • AppScan扫描电脑上的客户端,C/S架构客户端等
  • 深度学习----卷积神经网络实现数字识别
  • RAW API 的 TCP 总结2
  • 数据结构8---排序
  • 鸿蒙OS与Rust整合开发流程
  • 【边缘计算】RK3576算力评估
  • 排序(Sort)方法详解(冒泡、插入、希尔、选择、堆、快速、归并)
  • 详细介绍Linux 内存管理 struct page数据结构中有一个锁,请问trylock_page()和lock_page()有什么区别?
  • 开源工具新玩法:cpolar提升Penpot协作流畅度
  • 8.28日QT