S7协议转HTTP协议

如下来源成都纵横智控-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格式上报。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值