dirkjanfaber / node-red-contrib-victron-vedirect-usb

Node-RED node for connecting to Victron equipment via a VE.Direct USB cable.
4 stars 1 forks source link

Incorrect Data Transmission When MPPT is Disconnected #8

Open simonbuehler opened 1 month ago

simonbuehler commented 1 month ago

hi,

thank you for maintaining and developing this node, it has been extremely useful.

I've noticed an issue that occurs when the MPPT is disconnected, such as when the battery is disconnected. In this scenario, the system continues to transmit the last received data. Although this situation might be rare in practical use, it would be better if no data were transmitted instead of sending incorrect or outdated data.

Thank you for looking into this.

simonbuehler commented 1 month ago

sorry my bad, the function node afterwards was doing stupid things, thanks for your work again !

simonbuehler commented 1 month ago

I've realized it might be related to the current logic of handling H1.

Current Logic:

if (data.H1) {
  nodeContext.set('d1', data)
  msg.payload = Object.assign({}, data, nodeContext.get('d2'))
} else {
  nodeContext.set('d2', data)
  msg.payload = Object.assign({}, data, nodeContext.get('d1'))
}

i guess the problem is this :

Suggestion:

How about simplifying it to always send the latest data?


dataReader.on('data', (data) => {
  const msg = {
    topic: 'VE.direct',
    payload: data
  }

  if (data.PID) {
    node.status({ fill: 'green', shape: 'dot', text: data.PID.product || '' })
  }

})

This way, we only deal with the freshest data. Thoughts? Am I missing something important about the H1 logic?

Thanks!

simonbuehler commented 1 month ago

this works for me

module.exports = function (RED) {
  'use strict'
  const VEDirect = require('../services/vedirect')
  const { SerialPort } = require('serialport')

  function VEDirectUSB(config) {
    RED.nodes.createNode(this, config)

    const node = this
    const dataReader = new VEDirect(config.port)
    let lastData = null
    let lastUpdateTime = null
    const dataStaleInterval = 5000 // 5 secs

    dataReader.on('data', (data) => {
      // Update the last received data and the timestamp
      lastData = data
      lastUpdateTime = Date.now()

      if (data.PID) {
        node.status({ fill: 'green', shape: 'dot', text: data.PID.product || '' })
      }
    })

    dataReader.on('error', (error) => {
      node.status({ fill: 'red', shape: 'dot', text: error })
      node.warn(error)
    })

    node.on('input', function (msg) {
      const currentTime = Date.now()
      if (lastData && (currentTime - lastUpdateTime) < dataStaleInterval) {
        msg.payload = lastData
      } else {
        msg.payload = {}
        node.status({ fill: 'yellow', shape: 'ring', text: 'data stale or unavailable' })
      }
      node.send(msg)
    })

    node.on('close', function () {
      dataReader.serial.close()
    })
  }

  RED.nodes.registerType('victron-vedirect-usb', VEDirectUSB)

  RED.httpNode.get('/victron/vedirect-ports', (req, res) => {
    SerialPort.list().then((ports) => {
      res.setHeader('Content-Type', 'application/json')
      res.send(ports)
    }, (err) => {
      console.log(err)
      res.status(500).send(err)
    })
  })
}