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

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

  • 设备接线准备
  • 设备调试
  • 代码实现
    • 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;计数器 方法四…

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

随着运营商技术升级、业务发展&#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. 边缘计算…

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

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

如何向PDB文件添加双键

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

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

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

需求是怎么一步一步变态的

最初的需求 需求是处理一些数据&#xff0c;数据例子&#xff1a; 而界面要显示的样子&#xff1a; 看起来不太难&#xff0c;可以分解出需求&#xff1a; 每一列的所有数据要都能参与选择&#xff0c;或者输入当一个参数选中之后&#xff0c;比如选中A选中1&#xff0c;则…

Jenkins用户管理(二):不同用户分配不同的任务访问权限

需求:不同用户访问到不同的Jenkins任务。 依赖插件:Role-based Authorization Strategy 1. 插件安装 进入【系统管理】-【插件管理】-【可用插件】,搜索Role-based Authorization Strategy进行安装,随后重启jenkins 2. 全局安全配置 进入【系统管理】-【全局安全配置】,【…

K8S:Pod容器中的存储方式及PV、PVC

文章目录 Pod容器中的存储方式一&#xff0e;emptyDir存储卷1.emptyDir存储卷概念2.emptyDir存储卷示例 二.hostPath存储卷1.hostPath存储卷概念2.hostPath存储卷示例 三.nfs共享存储卷1.nfs共享存储卷示例 四.PV和PVC1.PV、PVC概念2.PVC 的使用逻辑及数据流向3.storageclass插…

自动化测试:yaml结合ddt实现数据驱动!

在pythonunittestseleniumddt的框架中&#xff0c;数据驱动常见有以下几种方式实现&#xff1a; Csv/txtExcelYAML 本文主要给大家介绍测试数据存储在YAML文件中的使用场景。首先先来简单介绍一下YAML。 1. 什么是YAML 一种标记语言类似YAML&#xff0c;它实质上是一种通用…

git安装配置教程

目录 git安装配置1. 安装git2. git 配置3.生成ssh key:4. 获取生产的密钥3. gitee或者github添加ssh-key4.git使用5. git 使用-本地仓库与远程仓库建立连接第一步&#xff1a;进入项目文件夹&#xff0c;初始化本地仓库第二步&#xff1a;建立远程仓库。 建立远程连接的小技巧 …