通过410s读取电表数据并接入物联网平台

news2024/10/5 10:18:15

通过410s读取电表数据并接入物联网平台

  • 设备接线准备
  • 设备调试
  • 代码实现
    • Modbus TCP Client 读取电表数据
      • 读取寄存器数据转成32bit Float格式
      • 然后使用modbusTCP Client 读取数据
    • 使用mqtt协议接入物联网平台
      • 最终代码实现

设备接线准备

在这里插入图片描述

设备调试

代码实现

Modbus TCP Client 读取电表数据

读取寄存器数据转成32bit Float格式

原理

/**
 * 
 *  17038,  7864 
参考 https://blog.csdn.net/qq_36270361/article/details/115823294

SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM
0100 0010 1000 1110 0000 1111 0101 1100

s = 0
e = (1000 0101)转10进制 133  - 127 = 6
尾数
000 1110 0000 1111 0101 1100
4#在尾数的左边有一个省略的小数点和1,这个1在浮点数的保存中经常省略,
1.000 1110 0000 1111 0101 1100
指数值e = 6,因此小数点向右移动6位,得到尾数值如下:
1000111.0 0000 1111 0101 1100

整数

1 *2^6 + 0 *2^5 + 0 *2^4 + 0 *2^3 + 1* 2^2 + 1 *2^1 + 1*2^0
64 + 0+0+0 + 4 + 2 + 1 
71
小数部分前面0太多可以忽略不记了

0 * 2^-1 + 0 * 2^-2 + 0 * 2^-3 + 0 * 2^-4 + 0 * 2^-5 ....
浮点数值 = 整数 + 小数 = 71 + 0 = 71
*/ 
function toFloat(s1, s2)
{
  // s1:第一个寄存器地址数据,s2:第二个寄存器地址数据
    //将输入数值short转化为无符号unsigned short
    const us1 = s1, us2 = s2; // int
    if (s1 < 0) us1 += 65536;
    if (s2 < 0) us2 += 65536;
    //sign: 符号位, exponent: 阶码, mantissa:尾数
    let sign, exponent; // int
    let mantissa; // float
    //计算符号位
    sign = parseInt(us1 / 32768); // js中只需要整数
    //去掉符号位
    let emCode = us1 % 32768; // int
    //计算阶码
    exponent = parseInt(emCode / 128);
    //计算尾数
    mantissa = (emCode % 128 * 65536 + us2) / 8388608; // float
    //代入公式 fValue = (-1) ^ S x 2 ^ (E - 127) x (1 + M)
    const S = Math.pow(-1, sign)
    const E = Math.pow(2, exponent - 127)
    const M = (1 + mantissa)
    return S * E * M;
}

然后使用modbusTCP Client 读取数据

// create an empty modbus client
const ModbusRTU = require("modbus-serial");
const client = new ModbusRTU();

// open connection to a tcp line
client.connectTCP("10.0.0.251", { port: 24 });
client.setID(1);
// read the values of 10 registers starting at address 0
// on device number 1. and log the values to the console.
setInterval(() => {
  console.log('-----read-----')
    client.readHoldingRegisters(4157, 10, (err, data) =>{
    // data: {
    //  data: [17038,  7864]
    //  buffer // buffer 数据 实际上转换出来就是data数组
    // } 
        if (data?.data){
          console.log(data.data);
          const powerData = toFloat(data.data[0], data.data[1])
          console.log('-------powerData------', powerData)
        }
    });
}, 3000);


使用mqtt协议接入物联网平台

const mqtt = require("mqtt");
const md5 = require('js-md5');

const secureId = "admin";
const secureKey = "adminkey";
const timestamp = new Date().getTime()
const username = `${secureId}|${timestamp}`
const password = md5(username + "|" + secureKey)
const config = {
  url: "mqtt://10.0.0.108:1883",
  productId: '1696816545212956672',
  clientId: "1704681506453053440", // 电表设备id
  host: '10.0.0.108',
  port: 1883
}

const mqttClient = mqtt.connect({
  clientId: config.clientId,
  username,
  password,
  host: config.host,
  port: config.port,
  protocol: 'mqtt'
}); //指定服务端地址和端口


// 推送数据
function publishData (key, value) {
  const msg  = {
    "deviceId": config.clientId,
    "properties": {
      [key]: value
    }
  }
  mqttClient.publish(`/${config.productId}/${config.clientId}/properties/report`,JSON.stringify(msg))
}

//连接成功
mqttClient.on("connect", function() {
  console.log("服务器连接成功");
  publishData('online_time', new Date().getTime()) // 上报一条上线的消息

});

最终代码实现

function toFloat(s1, s2)
{
  // s1:第一个寄存器地址数据,s2:第二个寄存器地址数据
    //将输入数值short转化为无符号unsigned short
    const us1 = s1, us2 = s2; // int
    if (s1 < 0) us1 += 65536;
    if (s2 < 0) us2 += 65536;
    //sign: 符号位, exponent: 阶码, mantissa:尾数
    let sign, exponent; // int
    let mantissa; // float
    //计算符号位
    sign = parseInt(us1 / 32768); // js中只需要整数
    //去掉符号位
    let emCode = us1 % 32768; // int
    //计算阶码
    exponent = parseInt(emCode / 128);
    //计算尾数
    mantissa = (emCode % 128 * 65536 + us2) / 8388608; // float
    //代入公式 fValue = (-1) ^ S x 2 ^ (E - 127) x (1 + M)
    const S = Math.pow(-1, sign)
    const E = Math.pow(2, exponent - 127)
    const M = (1 + mantissa)
    return S * E * M;
}
// create an empty modbus client
const ModbusRTU = require("modbus-serial");
const client = new ModbusRTU();

// open connection to a tcp line
client.connectTCP("10.0.0.251", { port: 24 });
client.setID(1);


const mqtt = require("mqtt");
const md5 = require('js-md5');

const secureId = "admin";
const secureKey = "adminkey";
const config = {
  url: "mqtt://10.0.0.108:1883",
  productId: '1696816545212956672',
  clientId: "1704681506453053440", // 电表设备id
  host: '10.0.0.108',
  port: 1883
}
let mqttClient = null
let reconnectInterval = 1000;
let reconnectTimer = null;


// 推送数据
function publishData (key, value) {
  const msg  = {
    "deviceId": config.clientId,
    "properties": {
      [key]: value
    }
  }
  mqttClient?.publish(`/${config.productId}/${config.clientId}/properties/report`,JSON.stringify(msg))
}


function createClient() {
  if(mqttClient){
    return;
  }
  const timestamp = new Date().getTime()
  const username = `${secureId}|${timestamp}`
  const password = md5(username + "|" + secureKey)
  mqttClient = mqtt.connect({
    clientId: config.clientId,
    username,
    password,
    host: config.host,
    port: config.port,
    protocol: 'mqtt',
  }); //指定服务端地址和端口


  
  //连接成功
  mqttClient?.on("connect", function() {
    console.log("服务器连接成功");
    publishData('online_time', new Date().getTime())
  });

  // 断线重连
  mqttClient.on('error', (error) => {
    console.log('error:',new Date().getTime(), error);
    reconnect();
  });

  mqttClient.on('end', () => {
    console.log('end-------:', new Date().getTime());
    reconnect();
  });
}

function reconnect() {
  console.log(`reconnecting in ${reconnectInterval}ms...`);
  reconnectTimer = setTimeout(createClient, reconnectInterval);
  reconnectInterval = Math.min(reconnectInterval * 2, 30000);
}

// 创建链接
createClient()




// read the values of 10 registers starting at address 0
// on device number 1. and log the values to the console.
setInterval(() => {
  console.log('-----read-----')
    client.readHoldingRegisters(4157, 2, (err, data) =>{
        if (data?.buffer){
          console.log(data.data);
          const powerData = toFloat(data.data[0], data.data[1])
          console.log('------powerData-------', powerData)
          publishData('total_working_energy', powerData)
        }
    });
},5 * 60 * 1000);

效果预览
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1032935.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【PLC GX Works2】创建一个工程

PLC GX Works2软件安装 https://www.jcpeixun.com/software/375 程序编写 1、工程中找到新建 2、新建 3、导航栏中选择第三行第一个&#xff0c;是全局软元件注释 4、修改软元件名x0为点动按钮&#xff0c;y1为电机&#xff0c;之后关闭即可。 5、左母线&#xff0c;右…

精彩回放|Fortinet保障联网车辆全生命周期信息安全

随着AI、云计算、物联网等技术的不断发展&#xff0c;汽车行业正在经历深刻的变革。然而&#xff0c;这种变革不仅带来了前所未有的机遇&#xff0c;也带来了许多挑战&#xff0c;其中最突出的是信息安全问题。在为期五期的垂直行业网络安全案例讲座的第一期“汽车行业网络安全…

好用的记笔记app选哪个?

当你在日常生活中突然获得了一个灵感&#xff0c;或者需要记录会议的重要内容&#xff0c;或者是学校课堂上的笔记&#xff0c;你通常会拿出手机&#xff0c;因为它总是在你身边&#xff0c;随时可用。这时候&#xff0c;一款好的记笔记App可以让你事半功倍。 敬业签是一款全面…

【在Ubuntu部署Docker项目】— PROJECT#1

一、说明 让我们深入了解 Docker。用docker构建web服务器。我们正在计划开发JavaScript API&#xff0c;建立MySQL数据库&#xff0c;并创建一个 PHP 网站使用 API 服务。Php Node.js Mysql — DockerSeries — Episode#1 二、系统架构概述 我们要构建的容器&#xff0c;是三…

多边形碰撞检测算法

1、AABB碰撞检测算法 AABB碰撞检测指轴对齐碰撞箱(Axis-aligned Bounding Box)&#xff0c;是分别从x轴向和y轴向进行碰撞检测的算法。即对于需要检测的物体A和物体B我们需要将其用A盒和B盒套起来&#xff0c;判断A盒和B盒在x轴向和y轴向是否发生碰撞&#xff0c;只有在x轴向和…

电气设备预防维护包含哪些内容

电力系统的可靠性对于工业和基础设施运行至关重要&#xff0c;而电气设备预防维护是确保电力系统长期安全可靠运行的关键。本文将重点介绍电气设备预防维护的标准和操作过程&#xff0c;以确保电力系统的稳定性和安全性。 电气设备预防维护的标准 电气设备预防维护需要遵循一系…

Linux怎么创建符号链接(也叫软链接)

2023年9月21日&#xff0c;周四下午 简单来说&#xff0c;符号链接就相当于Windows中的快捷方式。 用如下命令就可以在Linux中创建符号链接&#xff1a; ln -s 被链接的文件 创建的符号链接的存放路径

Vue3如何优雅的加载大量图片?

前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 表妹一键制作自己的五星红旗国庆头像&#xff0c;超好看 最近开发了一个功能&#xff0c;页面首页会加载大量的图片&#xff0c;初次进入页面时&#xff…

干货,某大厂小姐姐深夜让我说出了秘密-springboot发邮件 原创

后端依赖 <!--引入mail依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency><!--使用thymeleaf构建邮件模板--><dependency><groupId&…

服务监控与优化之负载均衡之负载最低优先

相关文章&#xff1a; 自己动手写分布式任务调度框架用 Java 代码实现负载均衡的五种常见算法手写实现RPC框架&#xff08;带注册中心&#xff09;本文完整代码地址&#xff1a;https://gitee.com/dongguabai/blog/tree/master/loadbalance 前段时间&#xff0c;我们有一台定…

【喜讯】斯歌上榜:中国信通院《高质量数字化转型产品及服务全景图》

喜讯&#xff01;9月15号&#xff0c;上海斯歌旗下品牌“纳比云”凭借卓越的自研成果及社会影响力&#xff0c;在众多候选企业中脱颖而出&#xff0c;成功入选由中国信通院发布的2023《高质量数字化转型产品及服务全景图》&#xff08;技术开发领域&#xff09;。 以下为中国信…

项目经理的“四定、五起、六法”工作法

大家好&#xff0c;我是老原。 说来&#xff0c;我也工作十多年了&#xff0c;就像很多刚入门的项目经理一样&#xff0c;一开始不知道怎么预设风险、沟通和团队协调不够好&#xff1b; 有的人就可以规避风险&#xff0c;人际往来和团队管理都信手拈来&#xff0c;整个项目顺…

【问题记录】解决“命令行终端”和“Git Bash”操作本地Git仓库时出现 中文乱码 的问题!

环境 Windows 11 家庭中文版git version 2.41.0.windows.1 问题情况 在使用 “命令行终端” 和 “Git Bash” 在本地Git仓库敲击命令时&#xff0c;对中文名称文件显示一连串的数字&#xff0c;如下所示&#xff1a;这种情况通常是由于字符编码设置不正确所引起的 解决办法 设置…

uniapp项目实践总结(二十)URLScheme 协议知识总结

导语&#xff1a;在日常开发过程中&#xff0c;我们经常可以碰到很多的调起某个应用&#xff0c;打开唤醒某个 APP&#xff0c;链式启动 App 等场景&#xff0c;背后就涉及到了 URLScheme 协议的相关知识&#xff0c;下面就简单介绍一下。 目录 简介常见 URL Scheme跳转方法实…

Vosviewer的安装与使用

Vosviewer的安装与使用 1 安装2 使用参考&#xff1a; 关于vosviewer我就不过多介绍了。 vosviewer与citespace有什么区别?在这里可以引用一下知乎的文章简要说明一下&#xff1a; 1.操作难易VOSviewer很简单&#xff0c;在官网下载的时候会附带一个英文手册&#xff0c;稍微…

YOLOv5、YOLOv8改进:Decoupled Head解耦头

目录 1.Decoupled Head介绍 2.Yolov5加入Decoupled_Detect 2.1 DecoupledHead加入common.py中&#xff1a; 2.2 Decoupled_Detect加入yolo.py中&#xff1a; 2.3修改yolov5s_decoupled.yaml 1.Decoupled Head介绍 Decoupled Head是一种图像分割任务中常用的网络结构&#…

中科驭数DPU芯片K2斩获2023年“中国芯”优秀技术创新产品奖

2023年9月20日&#xff0c;中科驭数DPU芯片K2在2023年琴珠澳集成电路产业促进峰会暨第十八届“中国芯”颁奖仪式上荣获“中国芯”优秀技术创新产品奖。 “中国芯”集成电路优秀产品榜单是由国家工信部门指导、中国电子信息产业发展研究院举办的行业权威评选活动。自2006年以来…

oracle截取字符串前几位用substr函数如何操作?

随着社会的发展&#xff0c;it行业越来越受到人们的追捧&#xff0c;oracle软件作为一款数据库开发软件&#xff0c;更是受到it人士的钦懒&#xff0c;它是为数据存储和管理构建出的数据库管理系统&#xff0c;主要应用于商业智能管理、通信业务、工作流程管理等方面&#xff0…

springboot整合MeiliSearch轻量级搜索引擎

一、Meilisearch与Easy Search点击进入官网了解&#xff0c;本文主要从小微型公司业务出发&#xff0c;选择meilisearch来作为项目的全文搜索引擎&#xff0c;还可以当成来mongodb来使用。 二、starter封装 1、项目结构展示 2、引入依赖包 <dependencies><dependenc…

【操作系统笔记十四】科普:POSIX 是什么

注&#xff1a;本文转载自该文章posix是什么都不知道&#xff0c;还好意思说你懂Linux&#xff1f; Linux开发者越来越多&#xff0c;但是仍然有很多人整不明白POSIX是什么。本文就带着大家来了解一下到底什么是POSIX&#xff0c;了解他的历史和重要性。 一、什么是 POSIX&…