Build log referencing incorrect line

I have a major problem with the build log of my projects. No matter the code if I have a build/compile time error the line referring to the syntax error isn’t referencing the correct line. For example i have a syntax error on line 119 and the build log tells me the error is on line 237 and shows the code on line 237 not line 119. I’ve tried inserting random syntax errors around my code and none of them show up properly referenced in the build log. I’ve tried different boards as well and the problem persists. I’ve tried uninstalling all packages and uninstalling atom then reinstalling with no success. I don’t know what else to do. Any advice?

Running windows 10 x64 up to date.

Could you provide a simple project to reproduce this issue?

I wasn’t able to reproduce easily on a simple project but on all of my larger projects this seems to occur. The simplest I have is this one:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <AsyncMqttClient.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <ESP8266HTTPUpdateServer.h>
#include <ESP8266WebServer.h>
#include <ArduinoOTA.h>
#include <ArduinoJson.h> // required for settings file to make it readable
#include <ESPmanager.h>
#include <EEPROM.h>

#include "Settings.h"

extern "C" {
#include "user_interface.h"
}

//timer objects and variables
os_timer_t myTimer;

bool tickOccured;

ESP8266WebServer HTTP(80);

const char * defaultSSID = "ssid";
const char * defaultPSK = "password";
ESPmanager settings(HTTP, SPIFFS, "ESPManager", defaultSSID , defaultPSK);




#ifdef _MQTT_
AsyncMqttClient mqttClient;
#endif
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 14

// Setup a oneWire instance to communicate with any OneWire devices
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

#define TEMPERATURE_PRECISION 12

int numberOfDevices; // Number of temperature devices found

DeviceAddress tempDeviceAddress; // We'll use this variable to store a found device address

WiFiUDP ntpUDP;

uint32_t CustomMillis = 0;

// You can specify the time server pool and the offset (in seconds, can be
// changed later with setTimeOffset() ). Additionaly you can specify the
// update interval (in milliseconds, can be changed using setUpdateInterval() ).
NTPClient timeClient(ntpUDP, "ntp2.is.co.za");

//variables
uint32_t stamp = 0;
uint32_t stamp1 = 0;
uint32_t stamp2 = 0;
uint32_t stamp3 = 0;
uint32_t stamp4 = 0;
uint32_t stamp5 = 0;
float temperature = 0;
byte hours = 0;
byte minutes = 0;
byte seconds = 0;
byte TempLimit = 100;
byte TempLimitMem = 100;
byte RelayState = 0;
byte Onhours = 6;
byte Onminutes = 1;
byte Onseconds = 0;
byte keep = 0;
byte CommandRec = 0;
byte mqttconnected = 0;

void setup() {
  pinMode(12, OUTPUT);
  digitalWrite(12,LOW);
  pinMode(13, INPUT);
  beginEEPROM();

  SPIFFS.begin();
  settings.begin();
  HTTP.begin();

  //WifiSetup();
  MQTTPreSetup();
  MQTTsetup();



  sensors.begin();
  sensors.setWaitForConversion(FALSE);


  numberOfDevices = sensors.getDeviceCount();

  for(int i=0;i<numberOfDevices; i++)
  {
    // Search the wire for address
    if(sensors.getAddress(tempDeviceAddress, i))
  	{
  		// set the resolution to TEMPERATURE_PRECISION bit (Each Dallas/Maxim device is capable of several different resolutions)
  		sensors.setResolution(tempDeviceAddress, TEMPERATURE_PRECISION);
  	}
  }

  timeClient.begin();
  timeClient.setTimeOffset(7200);

  user_init();

  stamp = millis();
  stamp1 = CustomMillis;
  stamp2 = stamp2 + 250;
  stamp3 = stamp2 + 500;

}

void loop() {
  uint32_t temp = RelayState;
  HTTP.handleClient();
	settings.handle();
  TempRequest();
  UpdateTime();
  if(mqttconnected) PublishMessage();
  TurnOffKettle();
  KeepTemp();
  TurnOnKettle();
  delay(0);
  if(temp != RelayState){
    stamp4 = CustomMillis;
  }
}

//wifi setup
void WifiSetup(){
  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);

  WiFi.begin("ssid", "password");

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }

}

//mqtt setup
void  MQTTPreSetup(){
#ifdef _MQTT_
  mqttClient.onConnect(onMqttConnect);
  mqttClient.onDisconnect(onMqttDisconnect);
  mqttClient.onMessage(onMqttMessage);
#endif
}

void MQTTsetup(){
#ifdef _MQTT_
  mqttClient.setServer("m.cloudmqtt.com", 111111);
  mqttClient.setKeepAlive(5).setCleanSession(false).setWill("topic/online", 2, true, "no").setCredentials("user", "pass").setClientId("myDevice");
  #ifdef _DEBUG_
  Serial.println("Connecting to MQTT...");
  #endif
  mqttClient.connect();
#endif
}



#ifdef _MQTT_
void PublishMessage(){
  if(CustomMillis - stamp3 >= 1000){
    byte first2 = temperature;
    byte second2 = (byte) ((temperature - first2) * 100);
    char mess[13] = {3,CommandRec,hours,minutes,seconds,first2,second2,RelayState,TempLimit,keep,Onhours,Onminutes,Onseconds};
    String Stringmess = "";
    for(int i = 0; i < 13 ; i ++ ){
      Stringmess.concat(mess[i]);
    }
    CommandRec = 0;
    uint16_t packetIdPub2 = mqttClient.publish("d/kettle0", 2, true, &Stringmess[0],13);
    stamp3 = CustomMillis;
  }
}

void onMqttConnect(bool sessionPresent) {
  mqttconnected = 1;
  uint16_t packetIdSub = mqttClient.subscribe("s/kettle0", 2);
}

void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
  mqttconnected = 0;
  ESP.restart();
}

void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
  byte CheckTopic = 1;
  String MatchTopic = "s/kettle0";
  for(int i = 0 ; i < strlen(topic) ; i++){
    if(topic[i] != MatchTopic[i]) CheckTopic = 0;
  }
  if(CheckTopic && payload[0] == 1){
    CommandRec = 1;
    RelaySwitch(12,keep);
  }else if(CheckTopic && payload[0] == 0) {
    CommandRec = 1;
    if(keep == 1) keep = 0;
    digitalWrite(12,LOW);
    RelayState |= 1;
    RelayState ^= 1;
  }else if(CheckTopic && payload[0] == 2){
    CommandRec = 1;
    RelaySwitch(12,1);
  }else if(CheckTopic && payload[0] == 3){
    CommandRec = 1;
    keep = payload[1];
    EEPROM.write(3,keep);
    EEPROM.commit();
  }else if(CheckTopic && payload[0] == 4){
    CommandRec = 1;
    Onhours = payload[1];
    Onminutes = payload[2];
    Onseconds = payload[3];
    EEPROM.write(0, Onhours);
    EEPROM.write(1, Onminutes);
    EEPROM.write(2, Onseconds);
    EEPROM.commit();
  }else if(CheckTopic && payload[0] == 5){
    CommandRec = 1;
    TempLimit = payload[1];
    TempLimitMem = TempLimit;
    EEPROM.write(4, TempLimit);
    EEPROM.commit();
  }else if(CheckTopic && payload[0] == 9){
    CommandRec = 1;
    ESP.restart();
  }
}
#endif

// start of timerCallback
void timerCallback(void *pArg) {
  CustomMillis++;
} // End of timerCallback

void user_init(void) {
  os_timer_setfn(&myTimer, timerCallback, NULL);
  os_timer_arm(&myTimer, 1, true);
} // End of user_init

//request the temperature every 1 second
void TempRequest() {
  if (CustomMillis - stamp1 >= 1000) {
    temperature = sensors.getTempCByIndex(0);
    sensors.requestTemperatures();
    stamp1 = CustomMillis;
  }
}

//update the time every 10 seconds
void UpdateTime(){
  if (CustomMillis - stamp2 >= 1000) {
    uint32_t tempstamp = CustomMillis;
    timeClient.forceUpdate();
    hours = timeClient.getHours();
    minutes = timeClient.getMinutes();
    seconds = timeClient.getSeconds();
    stamp2 = CustomMillis;
  }
}

void TurnOffKettle(){
  if(((CustomMillis - stamp4 >= 300000) && (RelayState & 1)) || (temperature >= TempLimit)){
    digitalWrite(12,LOW);
    TempLimit = TempLimitMem;
    RelayState |= 1;
    RelayState ^= 1;
  }
}

void TurnOnKettle(){
  if(hours == Onhours && minutes == Onminutes && seconds == Onseconds){
    TempLimitMem = TempLimit;
    TempLimit = 100;
    if(keep == 2) RelaySwitch(12,0);
    else RelaySwitch(12,1);
  }
}

void KeepTemp(){
  if(keep == 1 && temperature < TempLimit - 10 && (RelayState & 1) == 0 && (CustomMillis - stamp5 <= 1800000)){
    digitalWrite(12,HIGH);
    RelayState |= 1;
    stamp4 = CustomMillis;
  }else if(CustomMillis - stamp5 >= 1800000){
    if(keep != 0){
      digitalWrite(12,LOW);
      keep = 0;
      TempLimit = TempLimitMem;
      RelayState |= 1;
      RelayState ^= 1;
    }
  }
}

void RelaySwitch(byte pin, byte keeper){
  digitalWrite(pin,HIGH);
  RelayState |= 1;
  keep = keeper;
  stamp4 = CustomMillis;
  if(keeper == 1){
    stamp5 = CustomMillis;
  }
}

void beginEEPROM(){
  EEPROM.begin(10);
  Onhours = EEPROM.read(0);
  Onminutes = EEPROM.read(1);
  Onseconds = EEPROM.read(2);
  keep = EEPROM.read(3);
  TempLimit = EEPROM.read(4);
}
aaaaaa

I get the error:

This obvious error is actually on line 336 at the very end but the error log indexes it beyond the last line of code for a some reason.

PlatformIO uses INO → CPP converter on-the-fly. Maybe, this issue is related to it. Try to rename KettleControl1.ino to KettleControl1.cpp. More details:

1 Like

At first glance that seemed to do the trick thank you very much. But shouldn’t this be flagged as a bug ie the converter isn’t referencing the correct lines in the INO file?

Yes, the final problem is hidden here. However, the initial problem is INO format. I don’t know who invented it and who uses it. INO is very bad format that can’t be directly linted with GCC and shows bad programming practice for embedded developer.

Please rename file to CPP and forget about all problems.