I'm trying to read the values of the property "GameRawData.ShowLights" from BeamNG in the Protocol Message Binding using an Ncalc formula, but having problems with the "in()" function: I'm testing using High Beam and Handbrake for my example.
The value of "GameRawData.ShowLights" seems to show the activated dashboard lights that match all the values of the property "DataCorePlugin.GameRawData.DashLights".
I'm trying to acheive the following:
- If "DL_HIGHBEAM" is in this list, output value of '1'
- If "DL_HANDBRAKE" is in this list, output value of '1'
This is the code I'm using (last line for debug only):
if(in('DL_HANDBRAKE', [GameRawData.ShowLights]), '1', '0') + ';' +
if(in('DL_HIGHBEAM', [GameRawData.ShowLights]), '1', '0') + ';' +
[GameRawData.ShowLights]
If only one of these values exists, I get an expected output of '1' (true). However, if more than 1 item is in the value then both statements return '0' (false)
Raw Result
When handbrake and high beams are on, the raw result is this:
0;0;DL_FULLBEAM, DL_HANDBRAKE
When only handbrake is on, the raw result is this:
1;0;DL_HANDBRAKE
Can anyone assist? Perhaps the value isn't a string and this won't work. I tried using padleft() to return the value as a string but that didn't work.
I ended up using Javascript. Here is my example for 12 relays, BMW E36 Cluster. Everything with GameData.Turn is not assigned to a relay.
Arduino Uno
var DL_SHIFT = 1 var DL_FULLBEAM = 2 var DL_HANDBRAKE = 4 var DL_PITSPEED = 8 var DL_TC = 16 var DL_SIGNAL_L = 32 var DL_SIGNAL_R = 64 var DL_SIGNAL_ANY = 128 var DL_OILWARN = 256 var DL_BATTERY = 512 var DL_ABS = 1024 if ($prop('GameData.Turn7') & DL_SHIFT ) var var1=0; else var1=1; if ($prop('GameRawData.ShowLights') & DL_SIGNAL_L) var var2=0; else var2=1; if ($prop('GameData.Turn9') & DL_TC) var var3=0; else var3=1; if ($prop('GameData.Turn10') & DL_TC) var var4=0; else var4=1; if ($prop('GameRawData.ShowLights') & DL_ABS) var var5=0; else var5=1; if ($prop('GameRawData.ShowLights') & DL_BATTERY) var var6=0; else var6=1; if ($prop('GameData.Turn13') & DL_TC) var var7=0; else var7=1; if ($prop('GameData.TurnA0') & DL_TC) var var8=0; else var8=1; if ($prop('GameData.TurnA1') & DL_TC) var var9=0; else var9=1; if ($prop('GameRawData.ShowLights') & DL_HANDBRAKE) var var10=0; else var10=1; if ($prop('GameRawData.ShowLights') & DL_OILWARN) var var11=0; else var11=1; if ($prop('GameRawData.ShowLights') & DL_FULLBEAM) var var12=0; else var12=1; if ($prop('GameRawData.ShowLights') & DL_SIGNAL_R) var var13=0; else var13=1; return (var1 + ";" + var2 + ";" + var3 + ";" + var4 + ";" + var5 + ";" + var6 + ";" + var7 + ";" + var8 + ";" + var9 + ";" + var10 + ";" + var11 + ";" + var12 + ";" + var13);
this is the shcustomprotocol.h
#ifndef __SHCUSTOMPROTOCOL_H__ #define __SHCUSTOMPROTOCOL_H__ #include <Arduino.h> class SHCustomProtocol { private: public: /* CUSTOM PROTOCOL CLASS SEE https://github.com/zegreatclan/SimHub/wiki/Custom-Arduino-hardware-support GENERAL RULES : - ALWAYS BACKUP THIS FILE, reinstalling/updating SimHub would overwrite it with the default version. - Read data AS FAST AS POSSIBLE in the read function - NEVER block the arduino (using delay for instance) - Make sure the data read in "read()" function READS ALL THE DATA from the serial port matching the custom protocol definition - Idle function is called hundreds of times per second, never use it for slow code, arduino performances would fall - If you use library suspending interrupts make sure to use it only in the "read" function when ALL data has been read from the serial port. It is the only interrupt safe place COMMON FUNCTIONS : - FlowSerialReadStringUntil('\n') Read the incoming data up to the end (\n) won't be included - FlowSerialReadStringUntil(';') Read the incoming data up to the separator (;) separator won't be included - FlowSerialDebugPrintLn(string) Send a debug message to simhub which will display in the log panel and log file (only use it when debugging, it would slow down arduino in run conditions) */ int p7; int p8; int p9; int p10; int p11; int p12; int p13; int pA0; int pA1; int pA2; int pA3; int pA4; int pA5; int PINHEAD7 = 7; int PINHEAD8 = 8; int PINHEAD9 = 9; int PINHEAD10= 10; int PINHEAD11= 11; int PINHEAD12= 12; int PINHEAD13= 13; int PINHEADA0 = A0; int PINHEADA1 = A1; int PINHEADA2 = A2; int PINHEADA3 = A3; int PINHEADA4 = A4; int PINHEADA5 = A5; // Called when starting the arduino (setup method in main sketch) // nicht 2,3,4,5,6 void setup() { pinMode(PINHEAD7,OUTPUT); pinMode(PINHEAD8,OUTPUT); pinMode(PINHEAD9, OUTPUT); pinMode(PINHEAD10,OUTPUT); pinMode(PINHEAD11,OUTPUT); pinMode(PINHEAD12,OUTPUT); pinMode(PINHEAD13,OUTPUT); pinMode(PINHEADA0, OUTPUT); pinMode(PINHEADA1,OUTPUT); pinMode(PINHEADA2, OUTPUT); pinMode(PINHEADA3,OUTPUT); pinMode(PINHEADA4, OUTPUT); pinMode(PINHEADA5,OUTPUT); digitalWrite(PINHEAD7,HIGH); digitalWrite(PINHEAD8,HIGH); digitalWrite(PINHEAD9, HIGH); digitalWrite(PINHEAD10,HIGH); digitalWrite(PINHEAD11,HIGH); digitalWrite(PINHEAD12,HIGH); digitalWrite(PINHEAD13,HIGH); digitalWrite(PINHEADA0, HIGH); digitalWrite(PINHEADA1,HIGH); digitalWrite(PINHEADA2, HIGH); digitalWrite(PINHEADA3,HIGH); digitalWrite(PINHEADA4, HIGH); digitalWrite(PINHEADA5,HIGH); } // Called when new data is coming from computer void read() { int p7 = FlowSerialReadStringUntil(';').toInt(); int p8 = FlowSerialReadStringUntil(';').toInt(); int p9 = FlowSerialReadStringUntil(';').toInt(); int p10 = FlowSerialReadStringUntil(';').toInt(); int p11 = FlowSerialReadStringUntil(';').toInt(); int p12 = FlowSerialReadStringUntil(';').toInt(); int p14 = FlowSerialReadStringUntil(';').toInt(); int pA0 = FlowSerialReadStringUntil(';').toInt(); int pA1 = FlowSerialReadStringUntil(';').toInt(); int pA2 = FlowSerialReadStringUntil(';').toInt(); int pA3 = FlowSerialReadStringUntil(';').toInt(); int pA4 = FlowSerialReadStringUntil(';').toInt(); int pA5 = FlowSerialReadStringUntil(';').toInt(); /* if(p7 == 0) { digitalWrite(PINHEAD7, LOW); } else { digitalWrite(PINHEAD7, HIGH); } */ if(p8 == 1) { digitalWrite(PINHEAD8, HIGH); } else { digitalWrite(PINHEAD8, LOW); } if (p9 == 0) { digitalWrite(PINHEAD9, LOW); } else { digitalWrite(PINHEAD9, HIGH); } /*if(p10 == 0) { digitalWrite(PINHEAD10, LOW); } else { digitalWrite(PINHEAD10, HIGH); } */ if(p11 == 1) { digitalWrite(PINHEAD11, HIGH); } else { digitalWrite(PINHEAD11, LOW); } if (p12 == 0) { digitalWrite(PINHEAD12, LOW); } else { digitalWrite(PINHEAD12, HIGH); } if (p13 == 0) { digitalWrite(PINHEAD13, LOW); } else { digitalWrite(PINHEAD13, HIGH); } if (pA0 == 0) { digitalWrite(PINHEADA0, LOW); } else { digitalWrite(PINHEADA0, HIGH); } if (pA1 == 0) { digitalWrite(PINHEADA1, LOW); } else { digitalWrite(PINHEADA1, HIGH); } if (pA2 == 0) { digitalWrite(PINHEADA2, LOW); } else { digitalWrite(PINHEADA2, HIGH); } if (pA3 == 0) { digitalWrite(PINHEADA3, LOW); } else { digitalWrite(PINHEADA3, HIGH); } if (pA4 == 0) { digitalWrite(PINHEADA4, LOW); } else { digitalWrite(PINHEADA4, HIGH); } if (pA5 == 0) { digitalWrite(PINHEADA5, LOW); } else { digitalWrite(PINHEADA5, HIGH); } } // Called once per arduino loop, timing can't be predicted, // but it's called between each command sent to the arduino void loop() { } // Called once between each byte read on arduino, // THIS IS A CRITICAL PATH : // AVOID ANY TIME CONSUMING ROUTINES !!! // PREFER READ OR LOOP METHOS AS MUCH AS POSSIBLE // AVOID ANY INTERRUPTS DISABLE (serial data would be lost!!!) void idle() { } }; #endif
Thank you very much for your reply, I ended up doing it slightly differently but this helped me understand what to do with the protocl message binding in Javascript!
Here's my solution, mine differs slightly due to a value of 1 requiring the digital write to be LOW, which turns ON the light:
Protocol Message Binding
var DL_FULLBEAM = 2 var DL_HANDBRAKE = 4 if ($prop('TurnIndicatorLeft')) var left=1; else left=0; if ($prop('TurnIndicatorRight')) var right=1; else right=0; if ($prop('GameRawData.ShowLights') & DL_FULLBEAM) var fullBeam=1; else fullBeam=0; if ($prop('GameRawData.ShowLights') & DL_HANDBRAKE) var handbrake=1; else handbrake=0; return (left + ';' + right + ';' + fullBeam + ";" + handbrake + ';');
shcustomprotocol.h
#ifndef __SHCUSTOMPROTOCOL_H__ #define __SHCUSTOMPROTOCOL_H__ #include <Arduino.h> class SHCustomProtocol { private: public: // game values int leftIndicator; int rightIndicator; int highBeam; int handbrake; // pins int leftIndicatorPin = 13; int rightIndicatorPin = 12; int highBeamPin = 11; int handbrakePin = 10; // Called when starting the arduino (setup method in main sketch) void setup() { // set pin as outputs pinMode(leftIndicatorPin, OUTPUT); pinMode(rightIndicatorPin, OUTPUT); pinMode(highBeamPin, OUTPUT); pinMode(handbrakePin, OUTPUT); // set default values to off // HIGH = off, assuming relay power connection is "normally-open" digitalWrite(leftIndicatorPin, HIGH); digitalWrite(rightIndicatorPin, HIGH); digitalWrite(highBeamPin, HIGH); digitalWrite(handbrakePin, HIGH); } // Called when new data is coming from computer void read() { // read values from custom protcol // IMPORTANT: Ensure custom protcol has values in this specific order! leftIndicator = FlowSerialReadStringUntil(';').toInt(); rightIndicator = FlowSerialReadStringUntil(';').toInt(); highBeam = FlowSerialReadStringUntil(';').toInt(); handbrake = FlowSerialReadStringUntil(';').toInt(); // Debug information FlowSerialDebugPrintLn("leftIndicator Value: " + String(leftIndicator)); FlowSerialDebugPrintLn("rightIndicator Value: " + String(rightIndicator)); FlowSerialDebugPrintLn("highBeam Value: " + String(highBeam)); FlowSerialDebugPrintLn("Handbrake Value: " + String(handbrake)); // Write pin values // TODO: need logic for hazard lights? if(leftIndicator == 1) { digitalWrite(leftIndicatorPin, LOW); } else { digitalWrite(leftIndicatorPin, HIGH); } if(rightIndicator == 1) { digitalWrite(rightIndicatorPin, LOW); } else { digitalWrite(rightIndicatorPin, HIGH); } if(highBeam == 1) { digitalWrite(highBeamPin, LOW); } else { digitalWrite(highBeamPin, HIGH); } if(handbrake == 1) { digitalWrite(handbrakePin, LOW); } else { digitalWrite(handbrakePin, HIGH); } } // Called once per arduino loop, timing can't be predicted, // but it's called between each command sent to the arduino void loop() { } // Called once between each byte read on arduino, // THIS IS A CRITICAL PATH : // AVOID ANY TIME CONSUMING ROUTINES !!! // PREFER READ OR LOOP METHOS AS MUCH AS POSSIBLE // AVOID ANY INTERRUPTS DISABLE (serial data would be lost!!!) void idle() { } }; #endif