S7协议转HTTP协议

embedded/2024/10/25 8:23:30/

如下来源成都纵横智控-https://www.iotrouter.com/

需求概述

本章要实现一个流程:EG8200采集西门子S7-200Smart的数据,并组装成JSON格式通过HTTP上报应用平台。
要采集的PLC点位表如下:

PLC

S7-200 Smart

IP

192.168.0.34/102

点表(DB1)

地址

数据类型

属性

名称

V0.0

Boolean

只读

风机1接触器异常

V0.6

Boolean

只读

风机2接触器异常

V1.6

Boolean

只读

风机3接触器异常

V2.5

Boolean

只读

变频器通讯故障

I0.0

Boolean

只读

电机高温报警

I0.1

Boolean

只读

温度状态异常

VD4

Float

只读

油压工程值

VD8

Float

只读

吸入压力工程值

VD12

Float

只读

燃油油位工程值

VD16

Float

只读

机柜温度值

VD20

Float

只读

发动机电压值

VD24

Float

只读

发动机电流值

VD28

Float

只读

发动机工作时间

VD32

Float

只读

泵压工程值

VW120

Unsigned16

只读

本机编号

VW750

Unsigned16

只读

本机组号

VW2402

Unsigned16

只读

电机1温度

VW2404

Unsigned16

只读

电机2温度

VW2406

Unsigned16

只读

电机3温度

VW2408

Unsigned16

只读

风机1温度

VW2410

Unsigned16

只读

风机2温度

VW2412

Unsigned16

只读

风机3温度

HTTP通信相关参数格式如下:



需求分析

在制作流程时,基础的逻辑是根据数据走向来制作流程。其中主要工作分为三步:
第一步:通过S7协议读取PLC变量数据,得到的数据存储在内存中(西门子节点)
第二步:将数据按照JSON格式进行格式化(函数节点)
第三步:配置HTTP 请求参数​

需求实现

1 采集PLC数据

从节点库拖入一个西门子节点,以及一个调试节点,调试节点用于查看读取到的PLC数据集,方便定位问题:

动画.gif

双击西门子节点,根据需求概述的内容填写对应的设置参数,如下图所示:


如果设置正确,调试窗口会有日志打印,显示的是读取到的数据内容:

动画.gif


有的时候PLC数据点比较多,手动依次录入比较繁琐。节点支持数据点的导入导出或者参数传递的方式来读取:

动画.gif

本例程用到的传参方案,函数节点内的代码如下:

2数据格式化

根据步骤引导,在调试窗口可以看到读到的PLC数据如下:

1699494702219.png


因为应用平台已经规定了数据必须按照JSON格式上报。接下来使用函数节点Javascrip代码将数据进行格式化,代码如下:

class DeviceReport {
    constructor(machineNumber, machineGroupNumber) {
        this.deviceInfo = {
            machineNumber: machineNumber,
            machineGroupNumber: machineGroupNumber
        };
        this.status = {
            fan1ContactError: 0,
            fan2ContactError: 0,
            fan3ContactError: 0,
            inverterCommError: 0,
            motorHighTempAlarm: 0,
            temperatureStatusError: 0
        };
        this.data = {
            oilPressure: 0,
            suctionPressure: 0,
            fuelLevel: 0,
            cabinetTemperature: 0,
            engineVoltage: 0,
            engineCurrent: 0,
            engineRuntime: 0,
            pumpPressure: 0,
            motor1Temperature: 0,
            motor2Temperature: 0,
            motor3Temperature: 0,
            fan1Temperature: 0,
            fan2Temperature: 0,
            fan3Temperature: 0
        };
        this.timestamp = null;
    }

    // 设置状态数据(1表示异常,0表示正常)
    setStatusData(statusData) {
        this.status = statusData;
    }

    // 设置传感器数据
    setSensorData(sensorData) {
        this.data = sensorData;
    }

    // 设置时间戳
    setTimestamp(timestamp) {
        this.timestamp = timestamp;
    }
    generateReport() {
        return {
            deviceInfo: this.deviceInfo,
            status: this.status,
            data: this.data,
            timestamp: this.timestamp
        };
    }
}

function dateFormat(fmt, timestamp) {
    let ret;
    const opt = {
        "Y+": timestamp.getFullYear().toString(), // 年
        "m+": (timestamp.getMonth() + 1).toString(),  // 月
        "d+": timestamp.getDate().toString(), // 日
        "H+": timestamp.getHours().toString(), // 时
        "M+": timestamp.getMinutes().toString(), // 分
        "S+": timestamp.getSeconds().toString() // 秒
    };
    for (let k in opt) {
        ret = new RegExp("(" + k + ")").exec(fmt);
        if (ret) {
            fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
        };
    };
    return fmt;
}
function setValue(data) {
    var myDeviceReport = new DeviceReport(data.VW120, data.VW750)
    var v0 = data.V0
    var v1 = data.V1
    var v2 = data.V2
    var i0 = data.I0
    var vd4 = data.VD4
    var vd2402 = data.VW2402
    const fmt = dateFormat("YYYY-mm-dd HH:MM:SS", new Date())
    try {
        // 设置状态数据
        const statusData = {
            fan1ContactError: v0[0],
            fan2ContactError: v0[6],
            fan3ContactError: v1[6],
            inverterCommError: v2[5],
            motorHighTempAlarm: i0[0],
            temperatureStatusError: i0[1]
        }
        myDeviceReport.setStatusData(statusData)

        // 设置传感器数据
        const sensorData = {
            oilPressure: vd4[0],
            suctionPressure: vd4[1],
            fuelLevel: vd4[2],
            cabinetTemperature: vd4[3],
            engineVoltage: vd4[4],
            engineCurrent: vd4[5],
            engineRuntime: vd4[6],
            pumpPressure: vd4[7],
            motor1Temperature: vd2402[0],
            motor2Temperature: vd2402[1],
            motor3Temperature: vd2402[2],
            fan1Temperature: vd2402[3],
            fan2Temperature: vd2402[4],
            fan3Temperature: vd2402[5]
        }
        myDeviceReport.setSensorData(sensorData)
        // 设置时间戳
        myDeviceReport.setTimestamp(fmt)
        //生成JSON对象返回
        return myDeviceReport.generateReport()
    } catch (err) {
        node.error(err.message);
        return null
    }

}
var plcData = msg.payload
if (setValue(plcData)){
    msg.payload = JSON.stringify(setValue(plcData),null,2)
    return msg
}


复制以上代码,粘贴到函数节点内,部署后即可看到效果:

动画.gif


可以看到,已经将读到的PLC数据,按照需求要求转换成了最终的JSON格式,且对数据进行了一定程度的计算(两位小数)。此处只是函数节点的冰山一角,因为支持Javascrip语言编程,几乎你能想到的任何功能都可以在这里实现。

3通过http周期上报

拖入一个HTTP节点,根据提示进行配置地址和请求方式,即可实现数据上报:

动画.gif

服务端返回成功,至此,数据上报已经完成,很简单几步即可实现:采集PLC数据并按照自定义JSON格式上报。


http://www.ppmy.cn/embedded/97989.html

相关文章

鸿蒙Harmony实战开发知识:“UIAbility组件的3种启动模式”

UIAbility的启动模式是指UIAbility实例在启动时的不同呈现状态。针对不同的业务场景,系统提供了三种启动模式: singleton启动模式 singleton启动模式为单实例模式,也是默认情况下的启动模式。 每次调用startAbility()方法时,如…

【系统架构设计】开发方法(二)

【系统架构设计】开发方法(二) 软件生命周期软件开发模型统一过程敏捷方法极限编程特征驱动开发Scrum水晶方法开放式源码ASD 软件重用基于架构的软件设计形式化方法 软件生命周期 软件开发模型 统一过程 敏捷方法 所谓敏捷开发,个人认为&…

HTTP协议中的Cookie和Session

文章目录 HTTP协议中的Cookie和Session1、HTTP协议中的Cookie1.1、概念1.2、工作原理1.3、分类1.4、安全性和用途1.5、Cookie基本格式1.6、代码Cookie测试 2、HTTP协议中的Session2.1、概念2.2、工作原理2.3、安全性和用途2.4、代码测试Session 3、总结和补充 HTTP协议中的Cook…

销售预测数据挖掘实战V2.0

1、概述 沃尔玛全年都会举办几次促销减价活动。这些减价活动都是在重要节假日之前进行的,其中最大的四个节假日是超级碗、劳动节、感恩节和圣诞节。包括这些节假日在内的几周在评估中的权重是非节假日周的五倍。在缺乏完整/理想历史数据的情况下,对这些…

Android内存优化之OnTrimMemory简介

Android内存优化之OnTrimMemory简介 一、前言二、 API 介绍2.1、哪些组件可以实现OnTrimMemory回调2.2、level参数的含义2.2.1、应用正在运行时:2.2.2、应用的可见性发生变化时:2.2.3、应用的进程位于后台 LRU 列表中时: 3、示例代码 三、拓展…

C++入门——19C++的类型转换

1.C语言的类型转换 C语言中总共有两种形式的类型转换:隐式类型转换和显式类型转换。 1. 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败 2. 显式类型转化:需要用户自己处理 oid Test () {int i …

每天一个数据分析题(四百八十三)- 统计推断

关于统计推断的内容,样本均值对总体均值的估计,满足下面哪些评价标准? A. 无偏性 B. 有效性 C. 一致性 D. 以上皆不是 数据分析认证考试介绍:点击进入 题目来源于CDA模拟题库 点击此处获取答案 数据分析专项练习题库 内容…

正点原子linux开发板 qt程序交叉编译执行

1.开发板光盘 A-基础资料->5、开发工具->1、交叉编译器->fsl-imx-x11-glibc-x86_64-meta-toolchain-qt5-cortexa7hf-neon-toolchain-4.1.15-2.1.0.sh 拷贝到 Ubuntu 虚拟机 用文件传输系统或者共享文件夹传输到linux虚拟机 用ls -l查看权限,如果是白色的使…