sebi2k1 / node-can

NodeJS SocketCAN extension
223 stars 73 forks source link

Register a listener very silent #128

Closed dsir-minute closed 1 year ago

dsir-minute commented 1 year ago

hi, i've discoverd this lib today, my setup is Armbian (23.8.1) aarch64 on an odroidc4 hardware on which I connected 2 serial to can adapters

this is my test app:

var can = require("socketcan");
var prompt = require('prompt-sync')();

// Parse database
var network = can.parseNetworkDescription("CPLC_A103.kcd");
var channel = can.createRawChannel("can1");
var db_motor = new can.DatabaseService(channel, network.buses["CPLC_A103_BUS"]);

channel.start();

// Register a listener to get signal1 value changes
db_motor.messages["CPLC_A103"].signals["Combo_EVSEPresentCurrent"].onChange(function(s) {
   console.log("Volts " + s.value);
});

var n = prompt('press enter to stop me...');
//while(true){}
channel.stop()
dsir-minute commented 1 year ago

as this is the content of my kcd file..

<NetworkDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://kayak.2codeornot2code.org/1.0" xsi:schemaLocation="Definition.xsd">
  <Document name="Some Document Name">some text</Document>
  <Node name="CPLC" id="1"/>
  <Bus name="CPLC_A103_BUS">
    <Message id="0x6D9" name="CPLC_A103" length="7" triggered="true" interval="3000">
      <Notes></Notes>
      <Producer>
        <NodeRef id="1"/>
      </Producer>
      <Signal name="Combo_EVSEPresentVoltage" offset="0" length="14" endianess="big">
        <Notes>

Event: true
Unavailable_Value: 0x3FFF</Notes>
        <Value slope="0.1" max="1000" unit="V"/>
      </Signal>
      <Signal name="Combo_EVSEPowerLimitAchieved" offset="15" endianess="big">
        <Notes>

Event: true
Unavailable_Value: 0b0</Notes>
        <LabelSet>
          <Label name="EVSE hasn't reached its power limit" value="0"/>
          <Label name="EVSE has reached its power limit" value="1"/>
        </LabelSet>
      </Signal>
      <Signal name="Combo_EVSECurrentLimitAchieved" offset="14" endianess="big">
        <Notes>

Event: true
Unavailable_Value: 0b0</Notes>
        <LabelSet>
          <Label name="EVSE hasn't reached its current limit" value="0"/>
          <Label name="EVSE has reached its current limit" value="1"/>
        </LabelSet>
      </Signal>
      <Signal name="Combo_EVSEPresentCurrent" offset="16" length="12" endianess="big">
        <Notes>

Event: true
Unavailable_Value: 0xFFF</Notes>
        <Value slope="0.1" max="400" unit="A"/>
      </Signal>
      <Signal name="Combo_EVSEVoltageLimitAchieved" offset="28" endianess="big">
        <Notes>

Unavailable_Value: 0b0</Notes>
        <LabelSet>
          <Label name="EVSE hasn't reached its voltage limit" value="0"/>
          <Label name="EVSE has reached its voltage limit" value="1"/>
        </LabelSet>
      </Signal>
      <Signal name="CPLC_CommunicationStatus" offset="36" length="3" endianess="big">
        <Notes>

Event: true
Unavailable_Value: 0b111</Notes>
        <LabelSet>
          <Label name="No HLC communication is established" value="0"/>
          <Label name="HLC communication is initializing" value="1"/>
          <Label name="HLC communication is ready to charge" value="2"/>
          <Label name="HLC communication is stopped (gestion pauses,opt)" value="3"/>
          <Label name="HLC communication error" value="4"/>
          <Label name="Not used" value="5"/>
          <Label name="Not used" value="6"/>
          <Label name="Unavailable" value="7"/>
        </LabelSet>
      </Signal>
      <Signal name="Combo_EVSEchargeHLCState" offset="32" length="4" endianess="big">
        <Notes>

Event: true
Unavailable_Value: 0x0</Notes>
        <LabelSet>
          <Label name="No HLC communication is established" value="0"/>
          <Label name="Communication &amp; Service setting is established" value="1"/>
          <Label name="Charge parameter Discovery response" value="2"/>
          <Label name="Cable Check response" value="3"/>
          <Label name="Precharge response" value="4"/>
          <Label name="Power delivery response" value="5"/>
          <Label name="Current demande response" value="6"/>
          <Label name="Metering receipt response" value="7"/>
          <Label name="Welding detection response" value="8"/>
          <Label name="Session stop response with EVSE (Station charging)" value="9"/>
          <Label name="Charging Status response" value="10"/>
          <Label name="ACchargeLoopReq" value="11"/>
          <Label name="Not used" value="12"/>
          <Label name="Not used" value="13"/>
          <Label name="Not used" value="14"/>
          <Label name="Not used" value="15"/>
        </LabelSet>
      </Signal>
      <Signal name="Combo_EVSEPeakCurrentRipple" offset="40" length="12" endianess="big">
        <Notes>

Event: true
Unavailable_Value: 0xFFF</Notes>
        <Value slope="0.1" max="400" unit="A"/>
      </Signal>
      <Signal name="CPLC_FaultType" offset="52" length="4" endianess="big">
        <Notes>

Event: true
Unavailable_Value: 0x0</Notes>
        <LabelSet>
          <Label name="No Fault" value="0"/>
          <Label name="Contract NOK" value="1"/>
          <Label name="Energy Transfer mode type not supported" value="2"/>
          <Label name="PLC comm failure HLCcommstatus" value="3"/>
          <Label name="EVSE comm Failure" value="4"/>
          <Label name="EVSE Not Ready" value="5"/>
          <Label name="EVSE Shutdown" value="6"/>
          <Label name="EVSE Utility Interrupt Event" value="7"/>
          <Label name="EVSE Isolation Monitoring Active" value="8"/>
          <Label name="EVSE Emergency Shutdown" value="9"/>
          <Label name="EVSE Malfunction Protocol with EVSE (Station charging)" value="10"/>
          <Label name="EVSE_Renegociate" value="11"/>
          <Label name="Not used" value="12"/>
          <Label name="Not used" value="13"/>
          <Label name="Not used" value="14"/>
          <Label name="Not used" value="15"/>
        </LabelSet>
      </Signal>
    </Message>
  </Bus>
</NetworkDefinition>
dsir-minute commented 1 year ago

the issue is: the js app never prints anything, but when its remplaced with a simple dump app, it shows the frames

the injection app (python) on the opposite side is this one an it is ok:

# I am injectorCanExt.py by mastermix
import sys
import time
from pathlib import Path
import canmatrix
import can
import cantools
import os
from pprint import pprint

default_cycle_time = 500
step_ms = .5

SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
OUTPUT_DBC_PATH = os.path.join(SCRIPT_DIR, 'CPLC_A103.kcd')

iterator1 = { 'name':'Combo_EVSEPresentVoltage', 'start': 2, 'stop': 1000, 'step': 100, 'v': 0, 'send':False }
iterator2 = { 'name':'Combo_EVSEPresentCurrent', 'start': 3, 'stop': 400, 'step': 50, 'v': 0, 'send':False }
iterator1['v'] = iterator1['start']
iterator2['v'] = iterator2['start']

iterator1['send'] = True if sys.argv[1]=='y' else False
iterator2['send'] = True if sys.argv[2]=='y' else False

CPLC_A103 = 1753

def main():
    # Read the DBC.
    db = cantools.db.load_file(OUTPUT_DBC_PATH)
    print("Loaded DBC from '{}'".format(OUTPUT_DBC_PATH))
    #print("db.messages ..")
    #print(db.messages)
    # Get a message to manipulate.
    message = db.get_message_by_name('CPLC_A103')
    #print(message)
    #print("CPLC_A103 signals ..")
    #pprint(message.signals)
    channel = "can0"
    bus = can.Bus(
        bustype="socketcan", channel=channel, fd=True, receive_own_messages=True
    )
    while True:
        try:
#########################################
            data = { 'Combo_EVSEPresentVoltage':0,
                'Combo_EVSEPowerLimitAchieved':0,
                'Combo_EVSECurrentLimitAchieved':0,
                'Combo_EVSEPresentCurrent':0,
                'Combo_EVSEVoltageLimitAchieved':0,
                'CPLC_CommunicationStatus':0,
                'Combo_EVSEchargeHLCState':0,
                'Combo_EVSEPeakCurrentRipple':0,
                'CPLC_FaultType':0
            }
#########################################
            if iterator1['send'] == True:
                print("%s=%f" % (iterator1['name'],iterator1['v']))
                data[iterator1['name']] = iterator1['v']
                iterator1['v'] += iterator1['step']
                if iterator1['v'] > iterator1['stop']:
                    iterator1['v'] = iterator1['start']
#########################################
            if iterator2['send'] == True:
                print("%s=%f" % (iterator2['name'],iterator2['v']))
                data[iterator2['name']] = iterator2['v']
                iterator2['v'] += iterator2['step']
                if iterator2['v'] > iterator2['stop']:
                    iterator2['v'] = iterator2['start']

            tosendData = db.encode_message(CPLC_A103,data=data,scaling=True, padding=True, strict=False)
            message = can.Message(arbitration_id=CPLC_A103, data=tosendData)
            #print(message)
            bus.send(message)

            time.sleep(.5)
        except KeyboardInterrupt:
            break
    bus.shutdown()
#----------------------------------------------------------------------------
if __name__ == "__main__":
    main()
dsir-minute commented 1 year ago

what could have I done wrong ? thank you !

sebi2k1 commented 1 year ago

Did you cross checked that any frames are received in your app in the first place? You can hookup a channel listener and print frames you received.

Second, I don’t know the prompt library in detail (does it block the main thread) but it could block the main event loop of nodejs and thus not receiving any frames.

did you tried the dump example of my extension (see samples)?

dsir-minute commented 1 year ago

I did use this and it prints all expected frames:

var can = require("socketcan");

var channel = can.createRawChannel("can1", true);

// Log any message
channel.addListener("onMessage", function(msg) { console.log(msg); } );

// Reply any message
//channel.addListener("onMessage", channel.send, channel);

channel.start();
dsir-minute commented 1 year ago

I did also replace the promt function with and infinite loop, and same absence of printed received frames

dsir-minute commented 1 year ago

I also did try with no prompt nor channel.stop() alas, still nothing going to the console!

sebi2k1 commented 1 year ago

Can you just add the channel message listener to your code and share the output?

dsir-minute commented 1 year ago

Can you just add the channel message listener to your code and share the output? here is my test2 variant if i understand you correctly :

var can = require("socketcan");
var prompt = require('prompt-sync')();
const dbFName = 'CPLC_A103.kcd'
const canInterface = 'can1'
const messageName = 'CPLC_A103'
// Parse database
var network = can.parseNetworkDescription(dbFName);
var channel = can.createRawChannel(canInterface);
console.log(`dbFName ${dbFName}, canInterface ${canInterface}`)
var db_motor = new can.DatabaseService(channel, network.buses["CPLC_A103_BUS"]);
channel.start();

// Register a listener to get signal1 value changes
db_motor.messages[messageName].signals["Combo_EVSEPresentCurrent"].onUpdate((s)=>{
   console.log("Volts " + s.value);
});
db_motor.messages[messageName].signals["Combo_EVSEPresentCurrent"].onChange((s)=>{
    console.log("VVolts " + s.value);
});
channel.addListener("onMessage", function(msg) { console.log(msg); } );

and here are the outputs :

raxy@odroidc4:~/rtChgPrice2-js$ node server
dbFName CPLC_A103.kcd, canInterface can1
{ id: 1753, ext: true, data: <Buffer 9c 40 fa 07 01 00 00> }
{ id: 1753, ext: true, data: <Buffer 7d 00 fa 07 01 00 00> }
{ id: 1753, ext: true, data: <Buffer 80 e8 fa 07 01 00 00> }
{ id: 1753, ext: true, data: <Buffer 84 d0 fa 07 01 00 00> }
{ id: 1753, ext: true, data: <Buffer 88 b8 fa 07 01 00 00> }
{ id: 1753, ext: true, data: <Buffer 8c a0 fa 07 01 00 00> }
{ id: 1753, ext: true, data: <Buffer 90 88 fa 07 01 00 00> }
^C
sebi2k1 commented 1 year ago

Check your sending code, the code sends extended frame format but according to your kcd file the signal is standard frame format, thus socketcans‘ database code doesn’t map the id as it expects standard frame format.

dsir-minute commented 1 year ago

ok, I suspected this mismatch on extended indication when it clearly should not be extended, tks !

dsir-minute commented 1 year ago

as I did not find how, in python, to force the extended id to false, i just replace my injector app with the js one below :+1:

var can = require("socketcan");
//var prompt = require('prompt-sync')();
const dbFName = 'CPLC_A103.kcd'
const canInterface = 'can1'
const messageName = 'CPLC_A103'

let iterator1 = { 'name':'Combo_EVSEPresentVoltage', 'start': 800, 'stop': 1000, 'step': 50, 'v': 0, 'send':false }
let iterator2 = { 'name':'Combo_EVSEPresentCurrent', 'start': 0, 'stop': 400, 'step': 25, 'v': 0, 'send':false }

// Parse database
var network = can.parseNetworkDescription(dbFName);
var channel = can.createRawChannel(canInterface);
console.log(`dbFName ${dbFName}, canInterface ${canInterface}`)
var myDBS = new can.DatabaseService(channel, network.buses["CPLC_A103_BUS"]);
//console.log(myDBS.messages)
channel.start();

myMsg = myDBS.messages[messageName]

setInterval(() => {
    iterator1['v'] += iterator1['step']
    if (iterator1['v'] > iterator1['stop'])
        iterator1['v'] = iterator1['start']
    myMsg.signals[iterator1.name].update(iterator1['v']);
    iterator2['v'] += iterator2['step']
    if (iterator2['v'] > iterator2['stop'])
        iterator2['v'] = iterator2['start']
    myMsg.signals[iterator2.name].update(iterator2['v']);
    console.log(`${iterator1['v']} volts, ${iterator2['v']} amps`)
    myDBS.send(messageName);
}, 500);

and now, all is as fine as it could be thanks again !!