Welcome, Guest. Please Login or Register
Arduino IDE for Visual Studio
 
 
When Logging a Support Issue in the Forum, please ensure you have also:-
  • Enabled vMicro > Compiler > Show Build Properties and Verbose
  • Re-Compile your program with these settings enabled
 
Save the new Output to a Text File and....
Support requests without the output above may be impossible to answer, so please help us to help you
 
  HomeSearch Tutorials & Wiki visualmicro.com LoginHelpRegister  
 
Page Index Toggle Pages: 1
Send Topic Print
Problem with structures (Read 357 times)
Marius
Developer
****
Offline



Posts: 192
Centurion RSA
Problem with structures
Jul 10th, 2019 at 4:43pm
 
Hi
I declared a structure as folllows:
Code (C++):
struct  ConfigObject {
  char hostname[64];
  int port;
};

const char *filename = "/config.txt";  // <- SD library uses 8.3 filenames
ConfigObject config;    



And get this error:
Code (C++):
JsonConfigFile.ino: 29:52: error: 'Config' does not name a type
 



It worked before in other sketches but now I have an error. Not sure if I must set some parameter.
Back to top
 
marius_d.liebenberg  
IP Logged
 
Visual Micro
Administrator
*****
Offline



Posts: 10617
United Kingdom
Re: Problem with structures
Reply #1 - Jul 10th, 2019 at 5:11pm
 
can you post a full ino
Back to top
 
WWW  
IP Logged
 
Marius
Developer
****
Offline



Posts: 192
Centurion RSA
Re: Problem with structures
Reply #2 - Jul 11th, 2019 at 7:45am
 
Code (C++):
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to store your project configuration in a file.
// It uses the SD library but can be easily modified for any other file-system.
//
// The file contains a JSON document with the following content:
// {
//   "hostname": "examples.com",
//   "port": 2731
// }
//
// https://arduinojson.org/v6/example/config/

#include <ArduinoJson.h>
#include <SD.h>
#include <SPI.h>

// Our configuration structure.
//
// Never use a JsonDocument to store the configuration!
// A JsonDocument is *not* a permanent storage; it's only a temporary storage
// used during the serialization phase. See:
// https://arduinojson.org/v6/faq/why-must-i-create-a-separate-config-object/

struct  ConfigObject {
  char hostname[64];
  int port;
};

const char *filename = "/config.txt";  // <- SD library uses 8.3 filenames
ConfigObject config;                         // <- global configuration object

// Loads the configuration from a file
void loadConfiguration(const char *filename, Config &config) {
  // Open file for reading
  File file = SD.open(filename);

  // Allocate a temporary JsonDocument
  // Don't forget to change the capacity to match your requirements.
  // Use arduinojson.org/v6/assistant to compute the capacity.
  StaticJsonDocument<512> doc;

  // Deserialize the JSON document
  DeserializationError error = deserializeJson(doc, file);
  if (error)
    Serial.println(F("Failed to read file, using default configuration"));

  // Copy values from the JsonDocument to the Config
  config.port = doc["port"] | 2731;
  strlcpy(config.hostname,                  // <- destination
          doc["hostname"] | "example.com",  // <- source
          sizeof(config.hostname));         // <- destination's capacity

  // Close the file (Curiously, File's destructor doesn't close the file)
  file.close();
}

// Saves the configuration to a file
void saveConfiguration(const char *filename, const Config &config) {
  // Delete existing file, otherwise the configuration is appended to the file
  SD.remove(filename);

  // Open file for writing
  File file = SD.open(filename, FILE_WRITE);
  if (!file) {
    Serial.println(F("Failed to create file"));
    return;
  }

  // Allocate a temporary JsonDocument
  // Don't forget to change the capacity to match your requirements.
  // Use arduinojson.org/assistant to compute the capacity.
  StaticJsonDocument<256> doc;

  // Set the values in the document
  doc["hostname"] = config.hostname;
  doc["port"] = config.port;

  // Serialize JSON to file
  if (serializeJson(doc, file) == 0) {
    Serial.println(F("Failed to write to file"));
  }

  // Close the file
  file.close();
}

// Prints the content of a file to the Serial
void printFile(const char *filename) {
  // Open file for reading
  File file = SD.open(filename);
  if (!file) {
    Serial.println(F("Failed to read file"));
    return;
  }

  // Extract each characters by one by one
  while (file.available()) {
    Serial.print((char)file.read());
  }
  Serial.println();

  // Close the file
  file.close();
}

void setup() {
  // Initialize serial port
  Serial.begin(9600);
  while (!Serial) continue;

  // Initialize SD library
  while (!SD.begin(4)) {
    Serial.println(F("Failed to initialize SD library"));
    delay(1000);
  }

  // Should load default config if run for the first time
  Serial.println(F("Loading configuration..."));
  loadConfiguration(filename, config);

  // Create configuration file
  Serial.println(F("Saving configuration..."));
  saveConfiguration(filename, config);

  // Dump config file
  Serial.println(F("Print config file..."));
  printFile(filename);
}

void loop() {
  // not used in this example
}

// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization or deserialization problem.
//
// The book "Mastering ArduinoJson" contains a case study of a project that has
// a complex configuration with nested members.
// Contrary to this example, the project in the book uses the SPIFFS filesystem.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
 

Back to top
 
marius_d.liebenberg  
IP Logged
 
Visual Micro
Administrator
*****
Offline



Posts: 10617
United Kingdom
Re: Problem with structures
Reply #3 - Jul 11th, 2019 at 2:25pm
 
It has always been the case that you need to place your own prototypes between the creation of a type and where they are first used.

Arduino IDE has moved to using a new system to deduce the location of prototypes which works most of the time. We will shortly move to the same.

The older system places them before first line of real code (non #include), which is why users types would always be placed in .h files. You can override by adding them yourself. Notice I have added prototypes for the save and load methods that make use of the types in their signatures.

Code (C++):
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to store your project configuration in a file.
// It uses the SD library but can be easily modified for any other file-system.
//
// The file contains a JSON document with the following content:
// {
//   "hostname": "examples.com",
//   "port": 2731
// }
//
// https://arduinojson.org/v6/example/config/

#include <ArduinoJson.h>
#include <SD.h>
#include <SPI.h>

// Our configuration structure.
//
// Never use a JsonDocument to store the configuration!
// A JsonDocument is *not* a permanent storage; it's only a temporary storage
// used during the serialization phase. See:
// https://arduinojson.org/v6/faq/why-must-i-create-a-separate-config-object/

struct  ConfigObject {
  char hostname[64];
  int port;
};

////// prototypes in correct location for cpp
//
void saveConfiguration(const char *filename, const Config &config);
void loadConfiguration(const char *filename, Config &config);
//
///////////////////

const char *filename = "/config.txt";  // <- SD library uses 8.3 filenames
ConfigObject config;                         // <- global configuration object

// Loads the configuration from a file
void loadConfiguration(const char *filename, Config &config) {
  // Open file for reading
  File file = SD.open(filename);

  // Allocate a temporary JsonDocument
  // Don't forget to change the capacity to match your requirements.
  // Use arduinojson.org/v6/assistant to compute the capacity.
  StaticJsonDocument<512> doc;

  // Deserialize the JSON document
  DeserializationError error = deserializeJson(doc, file);
  if (error)
    Serial.println(F("Failed to read file, using default configuration"));

  // Copy values from the JsonDocument to the Config
  config.port = doc["port"] | 2731;
  strlcpy(config.hostname,                  // <- destination
          doc["hostname"] | "example.com",  // <- source
          sizeof(config.hostname));         // <- destination's capacity

  // Close the file (Curiously, File's destructor doesn't close the file)
  file.close();
}

// Saves the configuration to a file
void saveConfiguration(const char *filename, const Config &config) {
  // Delete existing file, otherwise the configuration is appended to the file
  SD.remove(filename);

  // Open file for writing
  File file = SD.open(filename, FILE_WRITE);
  if (!file) {
    Serial.println(F("Failed to create file"));
    return;
  }

  // Allocate a temporary JsonDocument
  // Don't forget to change the capacity to match your requirements.
  // Use arduinojson.org/assistant to compute the capacity.
  StaticJsonDocument<256> doc;

  // Set the values in the document
  doc["hostname"] = config.hostname;
  doc["port"] = config.port;

  // Serialize JSON to file
  if (serializeJson(doc, file) == 0) {
    Serial.println(F("Failed to write to file"));
  }

  // Close the file
  file.close();
}

// Prints the content of a file to the Serial
void printFile(const char *filename) {
  // Open file for reading
  File file = SD.open(filename);
  if (!file) {
    Serial.println(F("Failed to read file"));
    return;
  }

  // Extract each characters by one by one
  while (file.available()) {
    Serial.print((char)file.read());
  }
  Serial.println();

  // Close the file
  file.close();
}

void setup() {
  // Initialize serial port
  Serial.begin(9600);
  while (!Serial) continue;

  // Initialize SD library
  while (!SD.begin(4)) {
    Serial.println(F("Failed to initialize SD library"));
    delay(1000);
  }

  // Should load default config if run for the first time
  Serial.println(F("Loading configuration..."));
  loadConfiguration(filename, config);

  // Create configuration file
  Serial.println(F("Saving configuration..."));
  saveConfiguration(filename, config);

  // Dump config file
  Serial.println(F("Print config file..."));
  printFile(filename);
}

void loop() {
  // not used in this example
}

// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization or deserialization problem.
//
// The book "Mastering ArduinoJson" contains a case study of a project that has
// a complex configuration with nested members.
// Contrary to this example, the project in the book uses the SPIFFS filesystem.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
 

Back to top
« Last Edit: Jul 11th, 2019 at 2:27pm by Visual Micro »  
WWW  
IP Logged
 
Marius
Developer
****
Offline



Posts: 192
Centurion RSA
Re: Problem with structures
Reply #4 - Jul 11th, 2019 at 2:49pm
 
That does not work either as you need the type declaration in the proto declaration.

Code (C++):
JsonConfigFile.ino: 34:52: error: 'Config' does not name a type
   void saveConfiguration(const char *filename, const Config &config)

JsonConfigFile.ino: 34:60: error: ISO C++ forbids declaration of 'config' with no type [-fpermissive]
   void saveConfiguration(const char *filename, const Config &config) 

Back to top
 
marius_d.liebenberg  
IP Logged
 
Visual Micro
Administrator
*****
Offline



Posts: 10617
United Kingdom
Re: Problem with structures
Reply #5 - Jul 11th, 2019 at 3:01pm
 
Sorry I should have added the prototypes after the type had been created + there are some bugs in your code. One example is that you changed the type name from Config to ConfigObject but you have not changed the type name within the rest of the code.

I have used the original json example to show the prototypes in the correct location alongside code that works.

Code (C++):
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
//
// This example shows how to store your project configuration in a file.
// It uses the SD library but can be easily modified for any other file-system.
//
// The file contains a JSON document with the following content:
// {
//   "hostname": "examples.com",
//   "port": 2731
// }

#include <ArduinoJson.h>
#include <SD.h>
#include <SPI.h>

// Configuration that we'll store on disk
struct Config {
  char hostname[64];
  int port;
};

const char *filename = "/config.txt";  // <- SD library uses 8.3 filenames
Config config;                         // <- global configuration object

void loadConfiguration(const char* filename, Config& config);
void saveConfiguration(const char* filename, const Config& config);

// Loads the configuration from a file
void loadConfiguration(const char *filename, Config &config) {
  // Open file for reading
  File file = SD.open(filename);

  // Allocate the memory pool on the stack.
  // Don't forget to change the capacity to match your JSON document.
  // Use arduinojson.org/assistant to compute the capacity.
  StaticJsonBuffer<512> jsonBuffer;

  // Parse the root object
  JsonObject &root = jsonBuffer.parseObject(file);

  if (!root.success())
    Serial.println(F("Failed to read file, using default configuration"));

  // Copy values from the JsonObject to the Config
  config.port = root["port"] | 2731;
  strlcpy(config.hostname,                   // <- destination
          root["hostname"] | "example.com",  // <- source
          sizeof(config.hostname));          // <- destination's capacity

  // Close the file (File's destructor doesn't close the file)
  file.close();
}

// Saves the configuration to a file
void saveConfiguration(const char *filename, const Config &config) {
  // Delete existing file, otherwise the configuration is appended to the file
  SD.remove(filename);

  // Open file for writing
  File file = SD.open(filename, FILE_WRITE);
  if (!file) {
    Serial.println(F("Failed to create file"));
    return;
  }

  // Allocate the memory pool on the stack
  // Don't forget to change the capacity to match your JSON document.
  // Use https://arduinojson.org/assistant/ to compute the capacity.
  StaticJsonBuffer<256> jsonBuffer;

  // Parse the root object
  JsonObject &root = jsonBuffer.createObject();

  // Set the values
  root["hostname"] = config.hostname;
  root["port"] = config.port;

  // Serialize JSON to file
  if (root.printTo(file) == 0) {
    Serial.println(F("Failed to write to file"));
  }

  // Close the file (File's destructor doesn't close the file)
  file.close();
}

// Prints the content of a file to the Serial
void printFile(const char *filename) {
  // Open file for reading
  File file = SD.open(filename);
  if (!file) {
    Serial.println(F("Failed to read file"));
    return;
  }

  // Extract each characters by one by one
  while (file.available()) {
    Serial.print((char)file.read());
  }
  Serial.println();

  // Close the file (File's destructor doesn't close the file)
  file.close();
}

void setup() {
  // Initialize serial port
  Serial.begin(9600);
  while (!Serial) continue;

  // Initialize SD library
  while (!SD.begin()) {
    Serial.println(F("Failed to initialize SD library"));
    delay(1000);
  }

  // Should load default config if run for the first time
  Serial.println(F("Loading configuration..."));
  loadConfiguration(filename, config);

  // Create configuration file
  Serial.println(F("Saving configuration..."));
  saveConfiguration(filename, config);

  // Dump config file
  Serial.println(F("Print config file..."));
  printFile(filename);
}

void loop() {
  // not used in this example
}

// See also
// --------
//
// The website arduinojson.org contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization or deserialization problem.
// Please check it out at: https://arduinojson.org/
//
// The book "Mastering ArduinoJson" contains a case study of a project that has
// a complex configuration with nested members.
// Contrary to this example, the project in the book uses the SPIFFS filesystem.
// Please check it out at: https://arduinojson.org/book/ 

Back to top
« Last Edit: Jul 11th, 2019 at 3:02pm by Visual Micro »  
WWW  
IP Logged
 
Marius
Developer
****
Offline



Posts: 192
Centurion RSA
Re: Problem with structures
Reply #6 - Jul 11th, 2019 at 3:31pm
 
Thanks that works now. The bugs were me mucking about to try and isolate the issue
Back to top
 
marius_d.liebenberg  
IP Logged
 
Visual Micro
Administrator
*****
Offline



Posts: 10617
United Kingdom
Re: Problem with structures
Reply #7 - Jul 11th, 2019 at 3:39pm
 
Great, Yep makes sense. When/if you create a new empty project the template adds a note about the prototypes but we need to move to using the ctags system Arduino uses.

If Microsoft hasn't of caused tool window chaos with VS2019 we would be working on that right now  Cry but the forward moves will be good for us  Smiley
Back to top
« Last Edit: Jul 11th, 2019 at 3:40pm by Visual Micro »  
WWW  
IP Logged
 
Page Index Toggle Pages: 1
Send Topic Print