0

Why do my function write_ACK_ONLY() change my global variable? Im passing the rxUartBuffer to write_ACK_ONLY() as data = new Array(20) but as you can se in the Log Output. The Function do change also the rxUartBuffer

Code Part

console.log(this.toHexString(rxUartBuffer));
this.write_ACK_ONLY(rxUartBuffer)
console.log(this.toHexString(rxUartBuffer));

log Output

aa|02|00|01|00|00|0b|00|00|00|00|00|00|00|00|00|00|01|1d|d5|
aa|02|00|01|00|40|0b|00|00|00|00|00|00|00|00|00|00|01|1d|d5|

Code

import {Module} from './module';
import {PCP} from './pcp';
import {Logic} from "./logic";


const SerialPort = require('serialport');
const Ready = require('@serialport/parser-ready');
const CRC = require('crc-full').CRC;
var gpio = require('rpi-gpio')
var gpiop = gpio.promise;

gpiop.setup(7, gpio.DIR_OUT);

export class RsBUS{
 /*SERIAL*/
 private port = new SerialPort('/dev/ttyS0', {
  baudRate: 19200, dataBits: 8
 });

 private pcp = new PCP();

// private ByteLength = require('@serialport/parser-byte-length')

// private PCP_BIT_ERR_A:number = 0x01;//BIT 1 vom STATUS BYTE [5]

 private uartCounter: number = 0;

 private crc8 = new CRC("CRC8", 8, 0xd5, 0x0000, 0x0000, false, false);

 private txBuffer:number[] = new Array(20);

 constructor(){
  const rxUartBuffer:number[] = new Array(20);
  let buf_len = rxUartBuffer.length;
  let txUartBuffer:number[] = new Array(20);
  let endOfTransmision:boolean = false;/*TRUE = END, FALSE = ANFANG der Übermittlung*/

  this.port.on('data', (rxData) =>{
   rxUartBuffer[this.uartCounter] = rxData[this.pcp.START];

   if(rxUartBuffer[this.uartCounter] == this.pcp.START_BIT){
       endOfTransmision = false;
       rxUartBuffer[this.uartCounter] = this.pcp.START_BIT;
   }

    this.uartCounter++; // Counter MUSS hier hochgezählt werden.

    /*FEHLER BEIM EMPFANGEN*/
    if(rxUartBuffer[this.pcp.START] != this.pcp.START_BIT){
      console.log("RS ERROR");
      this.uartCounter = 0;
        //write_ERROR_ALL(0x02); //0b00000010 = ERR Bit
        //SENDE AN ALLE "HAB ICH NICHT VERSTNANDEN" > "DER, der kein ACK bekommen hat, sendet nochmal"
   }

   if(rxUartBuffer[this.uartCounter-1] == this.pcp.END_BIT){ //counter wird vorher schon hochgezählt
     console.log("\nEnde angekommen");
     endOfTransmision = true;
   }

    if(this.uartCounter == 20 && rxUartBuffer[this.pcp.START] == this.pcp.START_BIT/* <--das testenm, und dann kann das --> weg: rxUartBuffer[this.PCP_START] == this.PCB_BIT_START*/){
    console.log("Daten erfolgreich empfangen!");
    //console.log(toHexString(rxUartBuffer));
    txUartBuffer = rxUartBuffer;
    this.uartCounter = 0;
    //CRC CHECK
    var crcCeckedBuffer = this.checkCrcChecksum(rxUartBuffer);

      if(crcCeckedBuffer){
        //CRC OK
        console.log("CRC OK!");
      this.logPCPHeader();
      console.log(this.toHexString(rxUartBuffer));
      this.write_ACK_ONLY(rxUartBuffer)
      console.log(this.toHexString(rxUartBuffer));
        this.analyzePCP(rxUartBuffer);
    //  this.write_ACK_ONLY(rxUartBuffer)

       }else{
        //CRC NOT OK
        console.log("CRC korrupt!");
        this.write_ERROR(txUartBuffer); //CRC EROR
       }
     }else if(endOfTransmision == true){ //ENDE DA, aber die 20 Byte sind noch nicht voll. Also Fehler
     console.log(this.uartCounter)
     console.log(rxUartBuffer[this.pcp.START])
     console.log(this.pcp.START_BIT)
      endOfTransmision = false;
      this.uartCounter = 0;
      console.log("Fehler beim empfangen!");
       //write_ERROR_ALL(0x02); //0b00000010 = ERR Bit
       //SENDE AN ALLE "HAB ICH NICHT VERSTNANDEN" > "DER, der kein ACK bekommen hat, sendet nochmal"
   }
  });
 }

 logPCPHeader(){
  console.log("00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19");
  console.log("--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--");
 }

 toHexString(byteArray) {
  return Array.from(byteArray, (byte:any)=>{
   return ('0' + (byte & 0xFF).toString(16)).slice(-2) + "|";
  }).join('')
 // console.log("\n");
 }
 /*ERROR_ALL erstmal außenvorlasen.
 //SENDE AN ALLE "HAB ICH NICHT VERSTNANDEN" > "DER, der kein ACK bekommen hat, sendet nochmal"
 Dh. Evtl. wird das garnicht benötigt da ja das Modul auf ein ACK wartet. Wird das nicht gesendet bzw. vom Modul empfangen dann schickt der die Daten erneut*/
 write_ERROR_ALL(ErrorBit){
  this.txBuffer[0]  = 0xAA;
  this.txBuffer[1]  = 0x3F; //SENDE AN ALLE
  this.txBuffer[5]  = ErrorBit;
  this.txBuffer[19] = 0xd5;

  gpiop.write(7, true);
     setTimeout(()=>{
      var crcCeckedBuffer = this.createCrcChecksum(this.txBuffer);
      this.port.write(crcCeckedBuffer, (err, result) => {
       this.uartCounter=0;
       if (err) {
        console.log('Error while sending message : ' + err);
       }
       if (result) {
        console.log('Response received after sending message : ' + result);
       }
      });
  },200);
  setTimeout(function(){ gpiop.write(7, false);},300);
 }

 write_ERROR(data = new Array(20)){
  gpiop.write(7, true);
  data[this.pcp.STATUS] = this.pcp.ERR_BIT;

     setTimeout(()=>{
      var crcBuffer = new Array(17);
      for(var i = 0;i<17;i++){
       crcBuffer[i] = data[i];
      }

      var crcCeckedBuffer = this.createCrcChecksum(data);

      this.port.write(crcCeckedBuffer, (err, result) => {
       console.log("Sende ERROR BIT");
       this.uartCounter=0;
       if (err) {
        console.log('Error while sending message : ' + err);
       }
       if (result) {
        console.log('Response received after sending message : ' + result);
       }
      });
  },200);
     setTimeout(function(){ gpiop.write(7, false);},300);
 }

 write_ACK_ONLY(data = new Array(20)){//SENDE NUR ACK ohne Daten, bzw. mit den Empfangen Daten
  gpiop.write(7, true);
  data[this.pcp.STATUS] = this.pcp.ACK_BIT ;

     setTimeout(() => {
      var crcCeckedBuffer = this.createCrcChecksum(data);
     // console.log(crcCeckedBuffer);
      this.port.write(crcCeckedBuffer, (err, result) => {
       console.log("Sende ACK");
       this.uartCounter=0;
       if (err) {
        console.log('Error while sending message : ' + err);
       }
       if (result) {
        console.log('Response received after sending message : ' + result);
       }
      });
  },200);
  setTimeout(function(){ gpiop.write(7, false);},300);
 }

 /*WIRD NOCH angepasst... oder? Vielleicht braucht man write_ACK garnicht?*/
 write_DATA(data = new Array(20)){
  gpiop.write(7, true);
  data[this.pcp.STATUS] |= this.pcp.ACK_BIT;

     setTimeout(()=>{
      var crcCeckedBuffer = this.createCrcChecksum(data);

      this.port.write(crcCeckedBuffer, (err, result) => {
       console.log("Sende Daten");
       this.uartCounter=0;
       if (err) {
        console.log('Error while sending message : ' + err);
       }
       if (result) {
        console.log('Response received after sending message : ' + result);
       }
      });
  },200);
  setTimeout(function(){ gpiop.write(7, false);},300);
 }

 analyzePCP(receivedPcp){//Hier vorher PCP_evaluate
  /*DASD SIT NEUES MODUL UND SO*/
  //neues Modul initialisieren
  console.log(receivedPcp[this.pcp.STATUS])
  switch(receivedPcp[this.pcp.STATUS]){
   case this.pcp.INIT_BIT:
   {
    // INIT
    console.log("Modul init");
    var id = new Module().initNewModule(receivedPcp, (newID:number)=>{
     //console.log(newID);
     receivedPcp[this.pcp.DATA1] = newID;/*0x0E soll eine neue ID darstellen*/
     receivedPcp[this.pcp.STATUS] = this.pcp.INIT_BIT;/*0x0E soll eine neue ID darstellen*/
     this.write_DATA(receivedPcp);
    });
    break;
   }
   case 0x00:
   {
    var mod = new Module(receivedPcp[this.pcp.RSADDR], receivedPcp[this.pcp.DEVTYPE]);
    new Logic().checkRuleByModule(mod);
   }
  }

  // if(receivedPcp[this.pcp.STATUS] == this.pcp.INIT_BIT){
  //  console.log("Modul init");
  //  var id = new Module().initNewModule(pcp, (newID)=>{
  //   //console.log(newID);
  //   pcp[this.pcp.DATA1] = newID;/*0x0E soll eine neue ID darstellen*/
  //   pcp[this.pcp.STATUS] = this.pcp.INIT_BIT;/*0x0E soll eine neue ID darstellen*/
  //   this.write_DATA(pcp);
  //  });
  // //ansonsten ACK
  // }else{
  //  this.write_ACK_ONLY(pcp);
  // }
 }

 /*Erstellt eine fertiges Buffer mit Checksumme z.b. uzm Verchicken*/
 private createCrcChecksum(buf):number[]{
  var crcBuffer = new Array(17);

    for(var i = 0;i<17;i++){
     /*SCHNAPPT SICH NUR die ersten 17 Bytes*/
     crcBuffer[i] = buf[i];
    }

    /*erstellt daraus eine Checksumme*/
    var crc8_result = this.crc8.compute(crcBuffer);
    /*und teilt sie auf in byte 17 und 18*/
    buf[17] = crc8_result >> 7;
   buf[18] = crc8_result & 0x7F;

  /*Den fertigen Buffer mit der Checksume gibt er zurück*/
  return buf;
 }

 /*prüft ob die Empfange Checksumme (steckt in Byte 17 & 18) gleich ist mit der neu erstellen aus den Bytes 0-16*/
 private checkCrcChecksum(buf):boolean{
  var crcBuffer = new Array(17);

    for(var i = 0;i<17;i++){
     /*SCHNAPPT SICH NUR die ersten 17 Bytes*/
     crcBuffer[i] = buf[i];
    }

    /*nimmt sich aus dem empfangsBUF die CRC aus 17 und 18*/
      var crc8_h = (buf[17]<<7);
    var crc8_complete = (buf[18] | crc8_h);

  /*prüft ob Checksume aus Byte 0-16 gleich ist der welche in Byte 17 und 18 empfangen wurde*/
  return crc8_complete == this.crc8.compute(crcBuffer);
 }
}
Michael Mitch
  • 403
  • 2
  • 7
  • 17
  • `txUartBuffer = rxUartBuffer;` looks like the same array to me. If you want to copy it to be a seperate copy: https://stackoverflow.com/questions/7486085/copy-array-by-value – epascarello Feb 12 '20 at 16:26
  • this is not the Point... look..in the function write_ACK_ONLY()... there is no rxUartBuffer or txUartBuffer.. There is a variabel "data"... and just "data" is changed data[this.pcp.STATUS] = this.pcp.ACK_BIT ; – Michael Mitch Feb 12 '20 at 17:13

2 Answers2

0

By default, a global variable can be modified by any function.

The keyword let provides a solution for preventing the modification of global variable beyond the scope of the function.

Example:

myVariable = 10

function fx() {

let myVariable = 5

console.log("myVariable inside fx : " + myVariable)

}

console.log("myVariable outside fx : " + myVariable)

In the above code, the keyword let allows temporary overwriting of myVariable inside fx() function only. This prevents the function from modifying the global variable.

Gopinath
  • 4,066
  • 1
  • 14
  • 16
  • I do not use the global Variable in the function. I'm passing the rxUartBuffer to write_ACK_ONLY()... And in this function chage my local "data" Variable – Michael Mitch Feb 12 '20 at 17:15
0

OK.. I GOT IT.. i can't just copy a Array with A = B... I need to use slice().

A=B.slice();

Javascript array.push on clone array modify original array

Michael Mitch
  • 403
  • 2
  • 7
  • 17