• Benvenuti su RaspberryItaly!
Benvenuto ospite! Login Login con Facebook Registrati Login with Facebook


Valutazione discussione:
  • 0 voto(i) - 0 media
  • 1
  • 2
  • 3
  • 4
  • 5

[-]
Tags
win su amp c salvataggio file iot dati

C# Win IoT & Salvataggio Dati su file
#1
Ciao a tutti.
Ho una nuova domandina (...per voi), domandona (....per me).
In prrtica stò realizzando un app che simula (per il momento) il funzionamento
di un semaforo.
Una parte grafica su display 7'' e dei led collegati al GPIO che simulano le luci.
(se va tutto bene poi collego i led tramite optoisolatori alla parte di potenza ed accendo
le vere e proprie lanterne semaforiche.)
Ovviamente l'applicazione consente di variare i tempi di verde, giallo etc,
posso variare il modo di funzionamento "automatico", "lampeggio", "tutto rosso"... etc etc.
e ho degli orari di accensione e spegnimento.
Vorrei che tutti questi dati non vadano persi se ad esempio si perde l'alimentazione.
Ho pensato ad una eeprom, ma dato che ho già della memoria a disposizione,
vorrei salvare tutti i dati in un file, che a sua volta viene letto quando parte l'applicazione.
In pratica il file deve essere salvato ogni volta che viene modificata un impostazione,
e all'avvio dell'applicazione viene letto e vengono settate le impostazioni come l'ultimo
salvataggio.
Le variabili che devono essere salvate sono sotto.
Non fate caso ai valori che ho assegnato, mi servivano solo per far girare l'app.
Codice:
       private int Modo_Funzionamento = 1;      // 1 = Automatico  -  2 = Lampeggio  -  4 = Tutto Rosso  -  8 = Manuale
       private int Passo = 0;
       private int Secondi_Passo = 0;
       private double Tempo_Tutto_Rosso = 3;
       private double Tempo_Verde_1 = 10;
       private double Tempo_Giallo_1 = 4;
       private double Tempo_Rosso_1 = 2;
       private double Tempo_Verde_2 = 10;
       private double Tempo_Giallo_2 = 4;
       private double Tempo_Rosso_2 = 2;
       private int Secondi = 0;
       private int Decimi_di_Secondi = 0;
       private int Decimi_di_Sec_Lampeggio = 0;

       private int Num_Giorno_Settimana_Inserzioni = 1;   // 1 = Lunedi  2 = Martedi ...... 6 = Sabato .... 0 = Domenica
       // private string Giorno_Settimana;
       private double[] Ora_Inserzione_1 = new double[7] { 20, 0, 0, 0, 0, 0, 0 };
       private double[] Ora_Inserzione_2 = new double[7] { 6, 0, 0, 0, 11, 0, 0 };
       private double[] Ora_Inserzione_3 = new double[7] { 0, 8, 0, 6, 0, 7, 0 };
       private double[] Ora_Inserzione_4 = new double[7] { 0, 0, 18, 0, 22, 0, 8 };
       private double[] Minuti_Inserzione_1 = new double[7] { 41, 50, 0, 14, 0, 0, 0 };
       private double[] Minuti_Inserzione_2 = new double[7] { 35, 0, 10, 0, 0, 52, 0 };
       private double[] Minuti_Inserzione_3 = new double[7] { 29, 0, 22, 0, 20, 0, 0 };
       private double[] Minuti_Inserzione_4 = new double[7] { 30, 0, 11, 8, 0, 42, 0 };
       private int[] Prog_Inserzione_1 = new int[7] { 2, 2, 1, 1, 1, 1, 2 };
       private int[] Prog_Inserzione_2 = new int[7] { 1, 1, 1, 2, 1, 1, 2 };
       private int[] Prog_Inserzione_3 = new int[7] { 1, 2, 1, 2, 1, 1, 1 };
       private int[] Prog_Inserzione_4 = new int[7] { 2, 1, 2, 2, 2, 1, 2 };

Sono tutti numeri, alcuni di tipo double ma solo perchè sono acquisiti da degli slider, a ma andrebbero bene anche tutti di tipo int.
Mi date dei suggerimenti?
P.S. Ricordate che state parlando con un vero inesperto....
Grazie grazie..
Risposta
#2
Io non so nulla di C#, ma credo che tu possa semplicemente salvare tutto su un file di testo sulla SD. L'unica cosa è che la SD non ama le scritture frequenti, che ne accorciano la vita.
Risposta
#3
Per salvare dei dati su files esistono molti metodi nel .NET framework (indipendentemente dal linguaggio utilizzato Big Grin).
Come sempre premetto che non ho ancora avuto modo di provare Win IoT, quindi non conosco tutte le limitazioni che possono esserci rispetto alla versione Full del framework.
La strada più semplice è probabilmente quella di sfruttare la serializzazione, ovvero la capacità di serializzare una tua classe in uno stream (normalmente un Xml stream), e la successiva deserializzazione per rileggere tali dati.
Dopo una veloce ricerca in internet ho visto che la serializzazione è gestita anche in IoT, solo che essendo una UWP l'utilizzo è leggermente differente rispetto a quello che si fa normalmente in ambiente desktop.


Riassumento (ovviamente tutto quello che segue è teorico, mi manca la pratica su IoT Tongue ):
Il metodo più semplice è mettere tutti i dati da salvare in una classe che avrà degli attributi particolari che permetteranno l'esecuzione della serializzazione.
Solitamente io chiamo la mia classe Settings (che fantasia)
Esempio:
Codice:
[DataContract]
public class Settings
{
   [DataMember]
   public string ValoreTesto { get; set; }

   [DataMember]
   public int ValoreIntero { get; set; }

   [DataMember]
   public double ValoreDouble { get; set; }

   // ....

   [IgnoreDataMember]
   public string ValoreNonSerializzato { get; set; }
}

Praticamente si deve utilizzare l'attributo [DataContract] per 'marcare' la classe serializzabile, ogni singolo membro da serializzare avrà invece l'attributo [DataMember]. Se ci sono elementi che si vuole omettere dalla serializzazione, esiste l'attributo [IgnoreDataMember]

Ora passiamo al salvataggio vero e proprio dei dati (e relativo caricamento).
Si tratta di aggiungere due metodi alla classe Settings, un metodo Serialize che effettual la serializzazione, e la controparte Deserialize per ricaricare i dati.
Solitamente io uso un metodo Save, che corrisponde al serialize, e la controparte Load per caricare i dati, con l'unica differenza che il Load lo implemento come metodo statico. Sempre in internet ho trovato un esempio applicabile alle UWP dove al poso di metodi nella classe vengono implementati due ExtensionMethods generici che permettono al serializzazione/deserializzazione di qualsiasi classe cha abbia gli attributi su menzionati.
I metodi sono i seguenti:
Codice:
public static class Extensions
{
   public static string Serialize<T>(this T obj)
   {
       var ms = new MemoryStream();
       // Write an object to the Stream and leave it opened
       using (var writer = XmlDictionaryWriter.CreateTextWriter(ms, Encoding.UTF8, ownsStream: false))
       {
           var ser = new DataContractSerializer(typeof(T));
           ser.WriteObject(writer, obj);
       }
       // Read serialized string from Stream and close it
       using (var reader = new StreamReader(ms, Encoding.UTF8))
       {
           ms.Position = 0;
           return reader.ReadToEnd();
       }
   }

   public static T Deserialize<T>(this string xml)
   {
       var ms = new MemoryStream();
       // Write xml content to the Stream and leave it opened
       using (var writer = new StreamWriter(ms, Encoding.UTF8, 512, leaveOpen: true))
       {
           writer.Write(xml);
           writer.Flush();
           ms.Position = 0;
       }
       // Read Stream to the Serializer and Deserialize and close it
       using (var reader = XmlDictionaryReader.CreateTextReader(ms, Encoding.UTF8, new XmlDictionaryReaderQuotas(), null))
       {
           var ser = new DataContractSerializer(typeof(T));
           return (T)ser.ReadObject(reader);
       }
   }
}

Il loro uso si traduce in questo modo (al posto della classe Foo tu dovrai usare la classe Settings):
Codice:
   public void TestSerializer()
   {
       var obj = new Foo()
       {
           SomeText = "Sample String",
           SomeNumber = 135,
           SomeDate = DateTime.Now,
           SomeBool = true,
       };

       // Try to serialize to string
       string xml = obj.Serialize();

       // Try to deserialize from string
       var newObj = xml.Deserialize<Foo>();
   }

Il link da cui ho preso l'esempio è il seguente: http://stackoverflow.com/questions/32446...0-uwp-apps

Spero possa aiutarti a risolvere il tuo problema (comunque eventualmente guarda la documentazione su File Stream & C per capire eventualmente come salvare 'manualmente' i dati).
Ciao

PS: Sembra che le classi da utilizzare per Win IoT per accedere ai files siano: StorageFolder e StorageFile
Risposta
#4
..... quasi mi dispiace vedere quanto tempo hai perso per spiegarmi qualcosa
che onestamente è più grande delle mia capacità. Huh
Comunque tutto tornerà utile.

Vediamo se riusciamo a farla più semplice......
.... se invece di tutte quelle variabili, dovessi salvare una singola stringa
di testo in un file, sarebbe più semplice?
Se si (....speriamo..) potresti indirizzarmi?
Grazie 1000
Risposta
#5
Perdonatemi la battuta, ma con Python è così facile!
Risposta
#6
Bhe, se si tratta di salvare 'manualmente' dei dati su file anche in C# è semplice Tongue  (o forse lo è per me che lavoro tutti i giorni con C#)

Ora non ho molto tempo per spiegare il tutto (e soprattutto non ho ancora installato Win IoT sul rasp per iniziare effettivamente a provare Blush )
Prova a vedere qui se riesci a 'capire' come usare StorageFile per scrivere/leggere manualmente dei dati (in questo caso appunto una stringa).
http://grogansoft.com/blog/?p=554
Risposta
#7
Allora......
Siamo alla frutta!!!
Ho finito di sviluppare la parte grafica e quindi di gestione della centralina.
Ho deciso di inserire tutti i dati delle varie impostazioni su una stringa di tot caratteri.
(Ogni carattere è un dato, poichè i primi 32 codici ascii sono di difficile gestione ad ogni dato ho aggiunto 40, i dati che devo gestire variano da 0 a 99 per cui ad esempio, se il dato da salvare è 77 sulla stringa sarà 77 ascii + 40 cioè 117 ascii cioè una "u").
Sono riuscito nella codifica e decodifica della stringa da salvare.
Unica cosa che mi manca è il salvataggio e lettura della stringa su un file all'interno della SD del Raspy.
Ammettiamo che l'apparecchiatura perda alimentazione, non vorrei perdere i dati impostati.
vorrei che all'apertura della app viene letto il file di impostazioni, e se viene modificata un impostazione il file viene sovrascritto con la nuova impostazione.
Forse ora chiedo troppo....
.... è possibile avere un esempio concreto per il salvataggio e lettura di un file chiamato impostazioni.txt inserito nel cod sottostante?

Ho letto qui: https://msdn.microsoft.com/it-it/library....110).aspx ma non riesco a capire se può funzionare anche su un dispositivo che monta WinIoT........
Forse forse la soluzione è qui dove mi ha indicato gigios: http://grogansoft.com/blog/?p=554, ma anche quì dopo delle prove non sono comunque riuscito.
Immaginiamo che questa sotto sia la mia MainPage.xaml.cs....
..... anzitutto è in questa pagina che va inserito il codice che chiedo? Oppure in un altra pagina?
Facciamola facile, solo una stringa, un pulsante per salvare, e uno per leggere...

Codice:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace App7
{
   /// <summary>
   /// An empty page that can be used on its own or navigated to within a Frame.
   /// </summary>
   public sealed partial class MainPage : Page
   {
       private string stringa_impostazioni = "))(((-+F,*4-+((*((*((*((*((*(()(()((*(()(()(()(()((*((*(()((*(()((*(()(()((*((*(()((*(()((*(()(()";
       public MainPage()
       {
           this.InitializeComponent();
       }

       private void Pulsante_Che_Salva_Click(object sender, RoutedEventArgs e)
       {

       }

       private void Pulsante_Che_Legge_Click(object sender, RoutedEventArgs e)
       {

       }
   }
}

Capisco che così me la metto giù semplice, ma con un esempio concreto riesco a capire molto più che arrabbatandomi a destra e manca.
Grazie... grazie
Risposta
#8
Ti chiedo di portare un minimo di pazienza che questa sera/notte provo ad attrezzare il rasp con Win10 e faccio due prove veloci.
Se trovo velocemente il modo di salvare/leggere i file ti rispondo aggiornando il tuo sorgente.
Risposta
#9
Eccomi qui!
Sono riuscito a far partire in fretta e furia Win 10 IoT e a provare il salvataggio di una stringa, con relativa lettura successiva.
Per provare velocemente il tutto ho sfruttato i due metodi descritti qui: http://grogansoft.com/blog/?p=554
Non guardare come sono chiamati in quanto devo ancora approfondire bene anch'io come gestire le varie chiamate async in UWP.

Il tuo codice dovrebbe diventare in questo modo:
Prima di tutto aggiungi i due metodi usati per scrivere e leggere una stringa su file:
Codice:
       async Task SaveStringToLocalFile(string filename, string content)
       {
           // saves the string 'content' to a file 'filename' in the app's local storage folder
           byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes(content.ToCharArray());

           // create a file with the given filename in the local folder; replace any existing file with the same name
           StorageFile file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);

           // write the char array created from the content string into the file
           using (var stream = await file.OpenStreamForWriteAsync())
           {
               stream.Write(fileBytes, 0, fileBytes.Length);
           }
       }

       public static async Task<string> ReadStringFromLocalFile(string filename)
       {
           // reads the contents of file 'filename' in the app's local storage folder and returns it as a string

           // access the local folder
           StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
           // open the file 'filename' for reading
           Stream stream = await local.OpenStreamForReadAsync(filename);
           string text;

           // copy the file contents into the string 'text'
           using (StreamReader reader = new StreamReader(stream))
           {
               text = reader.ReadToEnd();
           }

           return text;
       }

Il secondo passaggio che ho fatto è stato quello di aggiungere due semplici metodi con cui chiamare i due metodi visti sopra (questo mi è servito per poter chiamare i metodi con await per aspettare il completamento della lettura. Come accennavo prima questo non credo sia il metodo corretto, ma devo ancora informarmi anch'io su come gestire async/await).
Codice:
       private async Task ExecuteSave()
       {
           await SaveStringToLocalFile("Prova.txt", "Testo scritto il " + DateTime.Now.ToString("F"));
       }

       private async Task ExecuteLoad()
       {
           string text = await ReadStringFromLocalFile("Prova.txt");
       }

Il metodo ExecuteSave non fa altro che salvare in un file di testo Prova.txt la stringa "Testo scritto il " concatenata alla data e ora dell'istante in cui il file è salvato (al momento la data è salvata in formato inglese).
ExecuteLoad è il metodo che legge dal file Prova.txt una stringa e la ritorna nella variabile text (e nel mio esempio non la usa a nulla).
L'ultima parte che manca è chiamare ExecuteLoad e Save nei tuoi eventi Click dei pulsanti definiti nel tuo xaml.
Codice:
      private void Pulsante_Che_Salva_Click(object sender, RoutedEventArgs e)
      {
          ExecuteSave();
      }

      private void Pulsante_Che_Legge_Click(object sender, RoutedEventArgs e)
      {
          ExecuteLoad();
      }

Come descritto nel sito linkato sopra, devi aggiungere anche i seguenti namespace all'inizio della tua classe:
Codice:
using System.Threading.Tasks;
using Windows.Storage;
using System.IO;

L'esempio postato l'ho imbastito in poco tempo senza prestare attenzione a scrivere codice pulito, quindi prendilo semplicemente come spunto di partenza.
Spero che possa esserti d'aiuto per continuare con il tuo codice.
Ciao.
Risposta
#10
Non ho parole.....
Grazie davvero grazie!!!
Stò leggendo di fretta in ufficio.
Poi più tardi provo a mettere giù quello che hai scritto.
Ovviamente ti farò sapere.
Ancora grazie.
Risposta
  


Vai al forum:


Navigazione: 1 Ospite(i)
Forum con nuovi Post
Forum senza nuovi post
Forum bloccato
Forum Redirect