reducing it presents the same problem, as in raising questions and what about this and that. 
the incoming record looks like this:
VLT=53.0, AMP=-30.2, AHR=-10, SOC=98, TMP=136, STS=192, ERR=0, AHM=400, RAW=3793, AAV=0, AZP=4095, TIM=0
the rest...
// -----------------------------------------------|--------------------------------
void loop() {
unsigned long timeStamp = millis(); // memorise current time
if (!mqttClient.connected()) {
// try establishing a connection to the MQTT server
if (timeStamp - lastReconnectAttempt > MQTT_RECONNECT_INTERVAL) {
lastReconnectAttempt = timeStamp;
digitalWrite(PIN_LED_MQTT_CONNECTED, LOW);
if (reconnect()) { // Attempt to reconnect
lastReconnectAttempt = 0;
digitalWrite(PIN_LED_MQTT_CONNECTED, HIGH);
}
}
} else {
mqttClient.loop(); // maintain connection & check for incoming messages
char recordIn[RECORD_IN_ARRAY_SIZE]; // one record in from BMS; every second a new one
char recordOut[RECORD_OUT_ARRAY_SIZE]; // one record out from BMS
// while there is data coming in through the serial port,
// ... read it, work it, and send it out via MQTT
while (SerialPortOne.available() > 0) {
char inByte = SerialPortOne.read(); // read byte
if (recordInByteCount < RECORD_IN_ARRAY_SIZE) {
// select the bytes we want = digits and .,-
if (isdigit(inByte) || inByte == '.' || inByte == ',' || inByte == '-') {
recordIn[recordInByteCount] = inByte; // add byte received to array
recordInByteCount++; // increment byte counter
recordIn[recordInByteCount] = '\0'; // add \o to end of array
}
}
if (inByte == '\n') { // if EOL send buffer
/*
* example record received by serial:
* Volt Ampere AmpereHours
* State of Charge
* Temperature
* Status Error
* VLT=53.0, AMP=-30.2, AHR=-10, SOC=98, TMP=136, STS=192, ERR=0,
* 1 2 3 4 5 6 7
* 0 1 2 3 4 5 6
* AHM=400, RAW=3793, AAV=0, AZP=4095, TIM=0
* 8 9 10 11 12
* 7 8 9 10 11
*
* TIM counts from 0-45; can be used to check if all records have been received
*/
loopCounter++; // increment temp reading loop counter
/*
* select values to show
* recordIn now contains: 53.0,-30.2,-10,98,136,192,0,400,3793,0,4095,42
* 56.0,0.5,-0,100,830,960,0,400,4100,10240,4095,20
* 08/07/2016 14:31:04,56.0,0.5,-0,100,24.75,0,
* 56.0,0.6,-0,100,828,960,0,400,4101,10752,4095,21
* 08/07/2016 14:31:06,56.0,0.6,-0,100,24.75,0,
* 56.0,0.5,-0,100,827,960,0,400,4100,11264,4095,22
* 08/07/2016 14:31:07,56.0,0.5,-0,100,24.75,0,
*/
//Serial.println(recordIn); // adds 28ms on UNO
//Serial.println(strlen(recordIn));
// create array of BMS values
int arrayElements = 12; // number of array values
char *arrValues[arrayElements]; // array holding values
arrValues[0] = strtok(recordIn, ","); // get first token
for (int j = 1; j <=arrayElements; j++) {
arrValues[j] = strtok(NULL, ","); // walk through other tokens
}
/*
* build recordOut like so:
* YYYY-MM-DD HH:mm:ss,55.9,1.2,-0,100,31.06,0,16
* 12345678901234567890123456789012345678901234567890
* 1 2 3 4 5
*/
char tmp[20];
//snprintf(tmp, "%d", year());
sprintf(tmp, "%d-%02d-%02d %02d:%02d:%02d", year(), month(), day(), hour(), minute(), second());
strcat(recordOut, tmp);
tmp[0] = '\0';
for (int i = 0; i <= 3; i++) { // VLT, AMP, AHR, SOC
strcat(recordOut, ","); // add delimiter
strcat(recordOut, arrValues[i]); // add value
}
controlSOC(atoi(arrValues[2])); // feed in AHR to calc SOC
if (loopCounter == 60) { // every 60 records (~60s) read temperature sensor
sensors.requestTemperatures(); // get temperatures
currentTemp = sensors.getTempCByIndex(0); // read 1st temperature sensor
loopCounter = 0; // reset
}
// dtostrf(floatVar, minStringWidthIncDecimalPoint, numVarsAfterDecimal, charBuf);
// here: temp float value, -12.34 (6), 2, buf = 6 + \0
char charBuf[7];
dtostrf(currentTemp, 6, 2, charBuf); // convert float to char
strcat(recordOut, ","); // add delimiter
strcat(recordOut, deblank(charBuf)); // add temperature
// get field 7 -- ERR error value // ERR
strcat(recordOut, ","); // add delimiter
strcat(recordOut, arrValues[6]); // add error value
// get field 12 -- TIM value // TIM = BMS record count (0-45)
strcat(recordOut, ","); // add delimiter
strcat(recordOut, arrValues[11]); // add received record count
Serial.println(recordOut);
mqttClient.publish(MQTT_PUB_BMS, recordOut);
// if SOC has changed, push new value via MQTT, connect first if required
if (controlValueOut != controlValueOutOld) {
// ----- MQTT publishing -----
// publish SoC
char bufSOC[7]; // 100.00 = 6 char + \0 = 7
dtostrf(controlValueOut, 6, 2, bufSOC);
mqttClient.publish(MQTT_PUB_BMS_SOC, deblank(bufSOC));
controlValueOutOld = controlValueOut;
// publish battery power (kW)
float batteryPower;
if (controlValueOut != 100 ) {
batteryPower = (atoi(arrValues[0]) * atoi(arrValues[1]) * 1.0);
} else {
/*
correct batteryPower to 0, because it may reach a SOC of 100% while still
showing a charge of up to 5kW -- Once the SoC has reached 100% the data
is no longer updated via MQTT, until the SoC changes again
*/
batteryPower = 0;
}
char bufBatteryPower[7]; // 5000.0 = 6 char + \0 = 7
dtostrf(batteryPower, 6, 2, bufBatteryPower);
mqttClient.publish(MQTT_PUB_BMS_BatteryPower, deblank(bufBatteryPower));
// publish battery capacity (kW)
float batteryCapacity = (20000 - (atoi(arrValues[0]) * abs(atoi(arrValues[2])) * 1.0)) / 1000;
char bufBatteryCapacity[8]; // 20000.0 = 7 char + \0 = 8
dtostrf(batteryCapacity, 7, 2, bufBatteryCapacity);
mqttClient.publish(MQTT_PUB_BMS_BatteryCapacity, deblank(bufBatteryCapacity));
}
recordIn[0] = '\0'; // empty array
recordOut[0] = '\0'; // empty array
recordInByteCount = 0; // reset byte counter
}
}
}
}
// --------------------------------------------------------------------------------
void controlSOC(float controlValue) {
/*
* SoC value to control Selectronic SP PRO GO
* analog out is 0-5V with 255 steps or 5/255 = 0.0196
* 100mv ~
* input: AHR = amp hour value for charge (+) and discharge (-) value
* -400 ~ 0% SoC to 0 = 100% SoC
* Battery capacity 400 AH
* calc: ((-AHR / AH) + 1) * 100 | (-172/400 = -0.43 - 1 = .57 * 100 = 57%
*/
// calc AD output value
controlValueOut = ((controlValue / BATT_CAPACITY_AH) + 1) * 100;
analogWrite(PIN_SOC_OUT, controlValueOut * 2.56);
}
// -----------------------------------------------|--------------------------------
char * deblank(char *str) {
// snatched; one day I will even understand it :-S
char *out = str, *put = str;
for (; *str != '\0'; ++str) {
if (*str != ' ')
*put++ = *str;
}
*put = '\0';
return out;
}
// -----------------------------------------------|--------------------------------
boolean reconnect() {
if (mqttClient.connect(MQTT_CONNECT_ID)) {
// e.g. mqttClient.subscribe(MQTT_SUB_something); // subscribe to hub pump demand
}
return mqttClient.connected();
}