数据流和关键代码如下:
1. 采集程序获取信息,生成如下json字符串,通过UDP发给127.0.0.1 4000。


{"type": "dianbiao", "tm": "2021-12-27 22:18:46", "Ua": 238.5, "Ub": 238.0, "Uc": 238.5,
 "Ia": 9.379, "Ib": 10.819, "Ic": 9.717, "Pt": 6.149, "Pa": 1851, "Pb": 2340, "Pc": 1958,
 "PF": 0.86, "Ep": 8777.900}

2. 下面的nodejs程序,在UDP 4000接收json字符串,并在TCP 4000端口接收socket.io访问

var PORT = 4000;
var HOST = '0.0.0.0';

var dgram = require('dgram');
var udpserver = dgram.createSocket('udp4');
udpserver.on('listening', function () {
  var address = udpserver.address();
  console.log('UDP Server listening on ' + address.address + ":" + address.port);
});
udpserver.bind(PORT, HOST);

function Utf8ArrayToStr(array) {
  var out, i, len, c;
  var char2, char3;

  out = "";
  len = array.length;
  i = 0;
  while (i < len) {
    c = array[i++];
    switch (c >> 4)
    { 
      case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
        // 0xxxxxxx
        out += String.fromCharCode(c);
        break;
      case 12: case 13:
        // 110x xxxx   10xx xxxx
        char2 = array[i++];
        out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
        break;
      case 14:
        // 1110 xxxx  10xx xxxx  10xx xxxx
        char2 = array[i++];
        char3 = array[i++];
        out += String.fromCharCode(((c & 0x0F) << 12) |
                                   ((char2 & 0x3F) << 6) |
                                   ((char3 & 0x3F) << 0));
        break;
    }
  }    
  return out;
}

function ab2str(buf) {
  return Utf8ArrayToStr(new Uint8Array(buf));
}

udpserver.on('message', function (msg, remote) {
  var txt = ab2str(msg);
  console.log(txt);
  try {
    var obj = JSON.parse(txt);
    io.emit('iot', obj);
  }
  catch (e) {
    console.log("json parse error");
    console.log(e);
  }
});

const { readFileSync } = require("fs");
const { createSecureServer } = require("http2");
const { Server } = require("socket.io");

const httpServer = createSecureServer({
  allowHTTP1: true,
  key: readFileSync("/etc/httpd/ssl/3_bg6cq.top.key"),
  cert: readFileSync("/etc/httpd/ssl/2_bg6cq.top.crt")
});

const io = new Server(httpServer, {
  cors: {
    origin: "https://bg6cq.top",
    methods: ["GET", "POST"]
  }
});

httpServer.listen(PORT);
3. 网页端收到后更新页面显示

<script src="https://bg6cq.top:4000/socket.io/socket.io.js"></script>
<script>
var socket = io("https://bg6cq.top:4000/",{
  cors:{
    origin:'*',
    credentials:true
  }
});
socket.on('iot', function(obj){
  if(obj.type == "dianbiao") {
    document.getElementById("tm").innerHTML = obj.tm;
    document.getElementById("Ep").innerHTML = obj.Ep.toFixed(3) + "kWh";
    document.getElementById("PF").innerHTML = obj.PF.toFixed(2);
    document.getElementById("Pt").innerHTML = obj.Pt.toFixed(3) + "kW";
    document.getElementById("Ua").innerHTML = obj.Ua.toFixed(1) + "V";
    document.getElementById("Ub").innerHTML = obj.Ub.toFixed(1) + "V";
    document.getElementById("Uc").innerHTML = obj.Uc.toFixed(1) + "V";
    document.getElementById("Ia").innerHTML = obj.Ia.toFixed(3) + "A";
    document.getElementById("Ib").innerHTML = obj.Ib.toFixed(3) + "A";
    document.getElementById("Ic").innerHTML = obj.Ic.toFixed(3) + "A";
    document.getElementById("Pa").innerHTML = obj.Pa.toFixed(0) + "W";
    document.getElementById("Pb").innerHTML = obj.Pb.toFixed(0) + "W";
    document.getElementById("Pc").innerHTML = obj.Pc.toFixed(0) + "W";
  }
});
</script>