【智能电表数据接入物联网平台实践】

智能电表数据接入物联网平台实践

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

设备接线准备

在这里插入图片描述

设备调试

代码实现

Modbus TCP Client 读取电表数据

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

原理

/*** *  17038,  7864 
参考 https://blog.csdn.net/qq_36270361/article/details/115823294SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM
0100 0010 1000 1110 0000 1111 0101 1100s = 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 shortconst us1 = s1, us2 = s2; // intif (s1 < 0) us1 += 65536;if (s2 < 0) us2 += 65536;//sign: 符号位, exponent: 阶码, mantissa:尾数let sign, exponent; // intlet 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", // 电表设备idhost: '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 shortconst us1 = s1, us2 = s2; // intif (s1 < 0) us1 += 65536;if (s2 < 0) us2 += 65536;//sign: 符号位, exponent: 阶码, mantissa:尾数let sign, exponent; // intlet 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", // 电表设备idhost: '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.mzph.cn/news/84386.shtml

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

相关文章

pymysql执行非查询语句会自动提交事务,关闭事务自动提交

一、前置条件 在mysql数据库生成数据&#xff1a; CREATE DATABASE mydatabase;CREATE TABLE Course (CourseID INT PRIMARY KEY,CourseName VARCHAR(100),Instructor VARCHAR(100),Credits INT,StudentID INT,FOREIGN KEY (StudentID) REFERENCES StudentInformation(Studen…

win10 Baichuan2-7B-Chat-4bits 上部署 百川2-7B-对话模型-4bits量化版

搞了两天才搞清楚跑通 好难呢,个人电脑 win10 ,6GB显存 个人感觉 生成速度很慢,数学能力不怎么行 没有ChatGLM2-6B 强,逻辑还行, 要求: 我的部署流程 1.下载模型 ,下载所有文件 然后 放到新建的model目录 https://huggingface.co/baichuan-inc/Baichuan2-7B-Chat-4bits/tr…

HarmonyOS之 组件的使用

一 容器 1.1 容器分类 Column表示沿垂直方向布局的容器。Row表示沿水平方向布局的容器。 1.2 主轴和交叉轴 主轴&#xff1a;在Column容器中的子组件是按照从上到下的垂直方向布局的&#xff0c;其主轴的方向是垂直方向&#xff1b;在Row容器中的组件是按照从左到右的水平方向…

怒刷LeetCode的第11天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;迭代 方法二&#xff1a;递归 方法三&#xff1a;指针转向 第二题 题目来源 题目内容 解决方法 方法一&#xff1a;快慢指针 方法二&#xff1a;Arrays类的sort方法 方法三&#xff1a;计数器 方法四…

Golang net/http 包中的 RoundTripper 接口详解

RoundTripper 是什么&#xff1f; RoundTripper 是 net/http 包中的一个接口&#xff0c;定义了处理 HTTP 请求返回和响应的方法&#xff0c;是 http.Client 结构体中执行 http 请求的核心部分。接口定义如下&#xff1a; type RoundTripper interface {RoundTrip(*Request)…

如何借助上线初期运维管理守住项目建设最后一公里

随着运营商技术升级、业务发展&#xff0c;以及服务能力要求提升&#xff0c;当下新建项目的交付或系统大版本升级大多数都需要历经千辛万苦才达到上线的彼岸。然而&#xff0c;项目上线并不意味着项目结束&#xff0c;“上线”也并不意味着终点&#xff0c;而是一个新的管理模…

Redis学习笔记--001

Redis快速入门 文章目录 Redis快速入门一、初识Redis1.1、NoSQL数据库1.2、Redis介绍1.3、[Redis](https://redis.io/)的安装 二、Redis常见命令2.1、Redis默认启动2.2、指定配置启动2.3、Redis开机自启设置 三、Redis客户端3.1、Redis命令行客户端3.2、图形化桌面客户端 四、r…

软件项目开发的流程及关键点

软件项目开发的流程及关键点 graph LR A[需求分析] --> B[系统设计] B --> C[编码开发] C --> D[测试验证] D --> E[部署上线] E --> F[运维支持]在项目开发的流程中&#xff0c;首先是进行需求分析&#xff0c;明确项目的目标和功能要求。接下来是系统设计&am…

【Vue.js】vue-cli搭建SPA项目并实现路由与嵌套路由---详细讲解

一&#xff0c;何为SPA SPA&#xff08;Single Page Application&#xff09;是一种 Web 应用程序的开发模式&#xff0c;它通过使用 AJAX 技术从服务器异步加载数据&#xff0c;动态地更新页面内容&#xff0c;实现在同一个页面内切换不同的视图&#xff0c;而无需整页刷新 1.…

优维低代码实践:图片和搜索

优维低代码技术专栏&#xff0c;是一个全新的、技术为主的专栏&#xff0c;由优维技术委员会成员执笔&#xff0c;基于优维7年低代码技术研发及运维成果&#xff0c;主要介绍低代码相关的技术原理及架构逻辑&#xff0c;目的是给广大运维人提供一个技术交流与学习的平台。 优维…

爬虫 — App 爬虫(一)

目录 一、介绍二、APP 爬虫常见反爬三、APP 抓包常用工具四、模拟器五、安装 APP1、下载 APP2、安装 APP 六、fiddler1、工作原理2、安装3、基本介绍 七、环境配置1、fiddler 的配置2、夜神模拟器的配置 八、案例 一、介绍 爬虫分类——数据来源 1、PC 端爬虫&#xff08;网页…

Multisim14.0仿真(二十)74LS161 4位同步二进制加法计数器

一、仿真原理图&#xff1a; 二、仿真效果图&#xff1a;

云计算的未来:云原生架构和自动化运维的崭露头角

文章目录 云计算的演进云原生架构1. 容器化2. 微服务3. 自动化部署和扩展4. 故障恢复 自动化运维1. 基础设施即代码&#xff08;IaC&#xff09;2. 运维自动化示例&#xff1a;使用Ansible自动化配置管理 3. 自动化监控和报警 未来展望1. 更多的自动化2. 多云混合云3. 边缘计算…

Matlab程序结构

目录 顺序结构循环结构1、for循环结构 分支结构1、if...end结构2、if...else...end结构3、switch...case...end结构 顺序结构 顺序结构是最简单的程序结构。用户在编写玩程序后&#xff0c;系统就将按照程序的实际位置逐一顺次执行。 例1&#xff1a;求a、b两个数组的和 >…

《DevOps实践指南》- 读书笔记(九)

DevOps实践指南 25. 附录附录 1 DevOps 的大融合精益运动敏捷运动Velocity 大会运动敏捷基础设施运动持续交付运动丰田套路运动精益创业运动精益用户体验运动Rugged Computing 运动 附录 2 约束理论和核心的长期冲突附录 3 恶性循环列表附录 4 交接和队列的危害附录 5 工业安全…

Calendar对象获取当前周的bug

项目场景&#xff1a; 双周项目管理&#xff0c;需要获取当前周为一年之中的第几周&#xff0c;原先的代码是用Calendar对象&#xff0c;先用setTime&#xff08;&#xff09;把当前时间传入&#xff0c;再用get&#xff08;3&#xff09;获取一年中的第几周 问题描述 实际发…

如何向PDB文件添加双键

在用PDB文件进行分子绘图的时候&#xff08;制作OBJ&#xff09;&#xff0c;发现像Atomic blender插件和PDB本身并不支持双键&#xff0c;需要对PDB文件进行修改&#xff0c;参照的该yt链接https://www.youtube.com/watch?vYNoow7qkwFA&t364s&ab_channelEdvinFako 即…

Secrets of RLHF in Large Language Models Part I: PPO

本文是LLM系列文章&#xff0c;针对《Secrets of RLHF in Large Language Models Part I: PPO》的翻译。 大型语言模型中RLHF的秘密&#xff08;上&#xff09;&#xff1a;PPO 摘要1 引言2 相关工作3 人类反馈的强化学习4 有益和无害的奖励模型5 PPO的探索6 评估和讨论局限性…

由于找不到d3dx9_43.dll,无法继续执行代码要怎么解决

D3DX9_43.dll是一个动态链接库文件&#xff0c;它是DirectX的一个组件&#xff0c;主要用于支持一些旧版本的游戏和软件。当电脑缺少这个文件时&#xff0c;可能会导致这些游戏和软件无法正常运行。例如&#xff0c;一些老游戏可能需要D3DX9_43.dll来支持图形渲染等功能。此外&…

UNIAPP利用canvas绘制图片和文字,并跟随鼠标移动

最近有个项目&#xff0c;要触摸组件&#xff0c;产生一条图片跟随移动&#xff0c;并显示相应的文字&#xff0c;在网上找了一些资料&#xff0c;终于完成构想&#xff0c;废话少说&#xff0c;直接上代码&#xff08;测试通过&#xff09; <template> <view>…