YAMLDuino icon indicating copy to clipboard operation
YAMLDuino copied to clipboard

load external yaml file

Open thijstriemstra opened this issue 3 years ago • 7 comments

Would be great to have an example that shows how to load a yaml file that is embedded on the device, e.g. a config.yaml.

would also like to know if it's possible to load a yaml file; modify structure (with a simple physical button to toggle a boolean value for example) and save back as a yaml file?

thijstriemstra avatar Oct 13 '22 21:10 thijstriemstra

hi, thanks for your feedback :+1:

if you're on esp32/esp8266 here's a snippet using fs::FS I'll be adding to the example folder soon

otherwise please specify your preferred architecture/device (and eventually filesystem)

the suggested approach to manage a config,yml file is deserializing the YAML into a JsonObject, then use ArduinoJson accessors to manipulate the data, then serialize back to YAML

with esp32/8266 arduino packages, the fs::File object can be used as a Stream, so the syntax is straightforfard and stays the same for Serial, HTTPClient, or any object that inherits from the Stream class.

#include <ArduinoJson.h>
#include <YAMLDuino.h>

#include <FS.h>
#include <SD.h>


void setup()
{
  Serial.begin(115200);

  if( ! SD.begin( SS ) ) {
    Serial.println("Could not start the SD");
    return;
  }

  fs::File file = SD.open("/config.yml");

  if( !file ) {
    Serial.println("Can't open file for reading");
    return;
  }

  DynamicJsonDocument json_doc(file.size()*2);

  auto err = deserializeYml( json_doc, file ); // convert yaml to json

  file.close();

  if( err ) {
    Serial.printf("Unable to deserialize YAML to JsonDocument: %s\n", err.c_str() );
    return;
  }

  JsonObject myConfig = json_doc.as<JsonObject>();

  myConfig["blah"] = "new value";

  file = SD.open("/config.yaml", FILE_WRITE);

  if( !file ) {
    Serial.println("Can't open file for writing");
    return;
  }

  size_t bytes_out = serializeYml( myConfig, file );

  file.close();

  Serial.printf("Written %d bytes\n", bytes_out );
}

void loop()
{

}

tobozo avatar Oct 13 '22 23:10 tobozo

if you're on esp32/esp8266

Correct. But I'd also like to use it on Teensy 3.6 and 4.x.

I'll be adding to the example folder soon

Thanks!

thijstriemstra avatar Oct 14 '22 18:10 thijstriemstra

Teensy 3.6 and 4.x.

I don't have such legendary items, but the cores seem to implement fs::FS so it shouldn't be very different.

The library may need some modifications though as it currently only supports the boards listed in the Readme, it may need some additional #if defined ARDUINO_TEENSY40 || defined ARDUINO_TEENSY36 or whatever macros the teensy core generates for Arduino.

Please let me know how this went, I'll be happy to add these boards to the supported devices list.

tobozo avatar Oct 14 '22 19:10 tobozo

I have just published version 1.2.5, there's a new example based on M5Stack (to keep the code simple) with an action button that toggles a boolean value and updates the yaml file.

tobozo avatar Oct 15 '22 19:10 tobozo

hey @thijstriemstra I managed to order two teensy 4.1 units :partying_face: , I also found a package URL to use instead of the faulty installer, and patched the library to compile with teensy core, changes are visible on the 1.3.0 branch.

I can't test the library until next tuesday delivery though, if you have the opportunity could you try to flash the updated test.ino sketch from the examples folder and provide the output from Serial console?

tobozo avatar Nov 10 '22 10:11 tobozo

Hi, thank you @tobozo, you are doing a great job! BTW about this issue, this is what works for me:


void Yaml2Json()
{
  File file = LittleFS.open(config_file);
    
  if( !file ) 
    Serial.println("Can't open test file for writing :-(");
  
  size_t filesize = file.size();
  char string[filesize]; 
  file.read((uint8_t *)string, sizeof(string));
  string[filesize] = '\0';
  file.close();

  String yaml_str_file = string;
  Serial.println();
  Serial.println("YAML File input: ");
  Serial.println(yaml_str_file);

  StringStream yaml_stream( yaml_str_file );
  String json_string;
  StringStream json_stream_output( json_string );
  serializeYml( yaml_stream, json_stream_output, YAMLParser::OUTPUT_JSON_PRETTY );
 
  StaticJsonDocument<512> doc;
  DeserializationError error = deserializeJson(doc, json_stream_output);  

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

GYBeccaria avatar Nov 11 '22 17:11 GYBeccaria

thanks @GYBeccaria

it should also work without storing the file content in a string

String json_string;
StringStream json_stream_output( json_string );

File file = LittleFS.open(config_file);
if( file ) { 
  serializeYml( (Stream*)&file, json_stream_output, YAMLParser::OUTPUT_JSON_PRETTY );
  file.close();

  // deserialize ...

}


tobozo avatar Nov 11 '22 17:11 tobozo