* * * *

Privacy Policy

Blog italiano

Clicca qui se vuoi andare al blog italiano su Lazarus e il pascal.

Forum ufficiale

Se non siete riusciti a reperire l'informazione che cercavate nei nostri articoli o sul nostro forum vi consiglio di visitare il
Forum ufficiale di Lazarus in lingua inglese.

Lazarus 1.0

Trascinare un file nel programma
DB concetti fondamentali e ZeosLib
Recuperare codice HTML da pagina web
Mandare mail con Lazarus
Stabilire il sistema operativo
Esempio lista in pascal
File INI
Codice di attivazione
Realizzare programmi multilingua
Lavorare con le directory
Utilizzare Unità esterne
TTreeView
TTreeview e Menu
Generare controlli RUN-TIME
LazReport, PDF ed immagini
Intercettare tasti premuti
Ampliare Lazarus
Lazarus e la crittografia
System Tray con Lazarus
UIB: Unified Interbase
Il file: questo sconosciuto
Conferma di chiusura di un applicazione
Liste e puntatori
Overload di funzioni
Funzioni a parametri variabili
Proprietà
Conversione numerica
TImage su Form e Panel
Indy gestiore server FTP lato Client
PopUpMenu sotto Pulsante (TSpeedButton)
Direttiva $macro
Toolbar
Evidenziare voci TreeView
Visualizzare un file Html esterno
StatusBar - aggirare l'errore variabile duplicata
Da DataSource a Excel
Le permutazioni
Brute force
Indy 10 - Invio email con allegati
La gestione degli errori in Lazarus
Pascal Script
Linux + Zeos + Firebird
Dataset virtuale
Overload di operatori
Lavorare con file in formato JSON con Lazarus
Zeos ... dietro le quinte (prima parte)
Disporre le finestre in un blocco unico (come Delphi)
Aspetto retrò (Cmd Line)
Lazarus 1.0
Come interfacciare periferica twain
Ubuntu - aggiornare free pascal e lazarus
fpcup: installazioni parallele di lazarus e fpc
Free Pascal e Lazarus sul Raspberry Pi
Cifratura: breve guida all'uso dell'algoritmo BlowFish con lazarus e free pascal.
Creare un server multithread
guida all'installazione di fpc trunk da subversion in linux gentoo
Indice
DB concetti fondamentali e connessioni standard
Advanced Record Syntax
DB concetti fondamentali e DBGrid
DB concetti fondamentali e TDBEdit, TDBMemo e TDBText
Advanced Record Syntax: un esempio pratico
Superclasse form base per programmi gestionali (e non)
Superclasse form base per programmi gestionali (e non) #2 - log, exception call stack, application toolbox
Superclasse form base per programmi gestionali (e non) #3 - traduzione delle form
Superclasse form base per programmi gestionali (e non) #4 - wait animation
Un dialog per la connessione al database:TfmSimpleDbConnectionDialog
Installare lazarus su mac osx sierra
immagine docker per lavorare con lazarus e free pascal
TDD o Test-Driven Development
Benvenuto! Effettua l'accesso oppure registrati.
Aprile 19, 2024, 01:03:05 am

Inserisci il nome utente, la password e la durata della sessione.

321 Visitatori, 0 Utenti

Autore Topic: Synapse e Domotica  (Letto 5026 volte)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Synapse e Domotica
« Risposta #15 il: Giugno 20, 2022, 10:56:52 pm »
Come dissi, non conosco Synapse, ma le caratteristiche di un socket sono comuni a tutti i componenti.

Sia i client TCP che i server TCP (come anche gli UDP) hanno la possibilità di sapere da che socket remoto (IP e Porta) arrivano i dati, quindi anche con un solo socket puoi tranquillamente rilevare i dati, perchè interrogando le sue proprietà puoi identificare la fonte.

Anche la velocità non è un problema (con un solo socket riesco a gestire flussi non compressi di decine di immagini da decine di megabyte).

Poi dipende dalla logica del tuo programma.

Ti faccio un esempio banale con Indy:

Codice: [Seleziona]
//Evento ricezione dati da socket UDP comune a tutte le schede remote
procedure TCardComm.fIdUDPServer1UDPRead(AThread: TIdUDPListenerThread;
  const AData: TIdBytes; ABinding: TIdSocketHandle);
var z: cardinal;
     fLastPeerIP: string;
     //fLastPeerPort: word;
     fLastData: TIdBytes;
begin
  //incrementa un contatore interno per diagnostica
  InterlockedIncrement64(fContatore);
  try
    //Rileva l'IP Remoto di connessione
    fLastPeerIP := ABinding.PeerIP;
    //Rileva la PORTA Remota (non è di interesse)
    //fLastPeerPort := ABinding.PeerPort;
    //Legge i dati ricevuti (e automaticamente svuota il buffer di ricezione)
    fLastData := AData;
    z := 0; //Tiene conto della corsia (un sensore per corsia)
    {$IFDEF DEBUG}
      if fLastPeerIP = '127.0.0.1' then
        begin
          z := 0;
        end
      else
    {$ENDIF}
    if fLastPeerIP = '192.168.137.11' then
      begin
        z := 0;
      end
    else
      if fLastPeerIP = '192.168.137.12' then
        begin
          z := 1;
        end
 ......
   Assegna i dati (FLastData) a qualche contenitore indicizzato da Z ed elabora, oppure li usi negli altri Thread

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

Diego1981

  • Full Member
  • ***
  • Post: 180
  • Karma: +0/-0
Re:Synapse e Domotica
« Risposta #16 il: Luglio 19, 2022, 01:45:46 pm »
Ciao Drago
una curiosità visto che mi sembra tu utilizzi molto la gestione dei socket per quella tipologia di "lavoro" che sto provando a realizzare
A livello proprio di logica di programmazione, io utilizzo il form principale per gestire la grafica (luci accese/spente, porte finestre aperte/chiuse, ec..),poi ho un thread che gestisce "l'ascolto" e ricezione delle "stringhe" dai dispositivi(che sono 10 server TCP/IP) e le smista ad un altro thread che le elabora e invia le risposte ai server, in più ho un altro thread che invia dei comandi MODBUS (sono 8 dispositivi modbus rtu collegati ad un convertitore rs845/TCP) , secondo la tua esperienza potrebbe essere una gestione corretta ?
A livello di velocità non sono proprio contento e sono convinto che il processo inerente al modbus rallenti molto
grazie in anticipo


DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Synapse e Domotica
« Risposta #17 il: Luglio 19, 2022, 08:06:35 pm »
Ciao, io come te uso dispositivi di campo che usano sia seriali 485 (a 1 Mbit) che modbus TCP (senza convertitori).

La logica dei Thread mi pare corretta, e se usi i componenti corretti non dovresti avere "buchi" sulle prestazioni.

Per quello che riguarda il modbus TCP (sia esso diretto che tramite convertitori con finali RTU), l'importante e che usi socket non bloccanti, oppure in alternativa usi un componente (per esteso un socket) per ogni dispositivo.

Su rete Ethernet da 100 Mbit, purtroppo i dispositivi industriali sono ancora alla Fast Ethernet, io interrogando via modbus TCP una periferica modbus (in questo caso PLC con modbus TCP hardware integrato) ho tempi di risposte (inteso tra l'invio comando e la ricezione risposta) intorno ai 2 o 3 millisecondi. Con altri dispositivi, dove ci sono convertitori di mezzo o non sono modbus hardware, difficilmente riesco a raggiungere velocità inferiori ai 80 ms. (in modo costante, diciamo facendo i test con 1000 invii / ricezioni).

In TCP il numero di dati che scambi è ininfluente sulla velocità, in RS485 (o RS232) il tempo di scambio dipende dal numero di dati che scambi e dalla velocità ... se hai una rete a 100 Mbit, ma la seriale del dispositivo è a 38400 baud (cioè 0,0384 Mbit) .... la differenza è decisamente apprezzabile.

Se vuoi, monitora i tempi con l'unità di diagnostica che allego (se non esiste già nell'ultima versione di Lazarus):
Codice: [Seleziona]
//Uso, aggiungi l'unità tra le Uses della tua Unità
Uses  Diagnostics;

//Puoi dichiarare quanti "timer" vuoi, anche come membri di classe, locali, ....
var HighTimer: TStopWatch;
.....

begin
  HighTimer := TStopWatch.StartNew;
  ...... //funzione da eseguire
  HighTimer.Stop;
  ShowMessage(fHighTimer.ElapsedMilliseconds.ToString); //In realtà puoi spingerti a misurare  multipli di 100 nanosecondi

  //Per eseguire un'altra misura
  HighTimer.Reset;
  HighTimer.Start;
  ...... //funzione da eseguire
  HighTimer.Stop;
  ShowMessage(fHighTimer.ElapsedMilliseconds.ToString);

end;

In questo modo puoi monitorare i tempi di ogni comunicazione e verificare dove stà il colle di bottiglia.
Puoi anche crearti un'array di timer, in modo da indicizzare tutte le tempistiche in un colpo solo (occhio al threading ovviamente, consiglio di utilizzare solo timer dichiarati nella propria unità).
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

Diego1981

  • Full Member
  • ***
  • Post: 180
  • Karma: +0/-0
Re:Synapse e Domotica
« Risposta #18 il: Luglio 20, 2022, 01:34:02 pm »
Grazie della risposta
effettivamente i tempi di risposta sul Modbus sono molto superiori agli 80 ms
provo a dare un'occhiata ai tuoi suggerimenti

Diego1981

  • Full Member
  • ***
  • Post: 180
  • Karma: +0/-0
Re:Synapse e Domotica
« Risposta #19 il: Agosto 12, 2022, 01:29:16 pm »
Buongiorno
ritorno sull'argomento multithreading (sperando di farmi capire  ;D)
ho il mio thread principale (chiamiamolo thread 1) in cui ho un array di record in cui vengono memorizzati dei valori di un input analogico (per l'esattezza la posizione della tapparelle di casa), questi valori vengono aggiornati dal "famigerato" thread secondario (chiamiamolo thread 2) che riceve le stringhe dalla scheda analogica via TCP/IP
Durante la movimentazione di una tapparella (poi saranno 13) viene aperto un altro thread secondario (chiamiamolo thread 3)  che controlla la posizione della tapparella andando a leggere il valore di quel record dall'array del thread principale (cioè il thread 1)
(ho scelto di aprire un nuovo thread con la speranza di riuscire a leggere la posizione esatta della tapparella per poterla fermare ad una determinata posizione , cosa che se invecefacessi nel secondo thread (cioè il thread 2) non avrei il tempo di fare perdendo la posizione di stop della tapparella all'altezza voluta quando andrei a movimentare tutte le tapparelle contemporanemente)
La domanda è:
come mai il valore analogico che vado a leggere nel thread principale (cioè il thread 1) è sempre quello corrispondente al valore nel momento in cui è stato creato il secondo thread secondario (cioè il thread 3) ?
(difficile da scrivere  ;D  ;D, forse pretendo troppo  ;D)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Synapse e Domotica
« Risposta #20 il: Agosto 12, 2022, 01:51:51 pm »
 :o

mi sono un attimo perso. Riassumo a mio modo per vedere se ho capito bene.

Thread 1 che semplicemente non fà nulla.

Thread 2 che comunica in "diretta" con le tapparelle e scrive i dati in un array aggiornandolo in tempo reale (reale ovviamente in funzione della velocità di comunicazione).

Thread 3 che monitorizza i valori dell'array per farsi i comodi suoi (ad esempio gestire un stop programmato delle tapparelle).

Tu dici che il valore dell'array che leggi  dal Thread 1 è sempre quello che leggi al momento in cui il Thread 3 inizia a monitorare l'array stesso.

Qualcosa che non và è certo, perchè se come dici tu l'array viene aggiornato SOLO dal Thread 2 allora tre sono le cose:

a) Il Thread 2 smette di comunicare e aggiornare l'array al momento in cui il Thread 3 incomincia a monitorare;

b) Qualche Thread (il 3 ?) và a scrivere nell'array;

c) L'array che leggi non è quello giusto, ovvero ci sono più istanze dell'array (ad esempio l'array è membro di tutti i Thread e per errore leggi e scrivi array diversi).

Hai provato ad esempio a non "lanciare" il Thread 3 e vedere se i dati dell'array variano correttamente ?

P.S.: come fai a visualizzare il valore dell'array? Debugger, TEdit, TMessageBox, ShowMessage, etc ...?

Ciao.
« Ultima modifica: Agosto 12, 2022, 01:55:05 pm da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

Diego1981

  • Full Member
  • ***
  • Post: 180
  • Karma: +0/-0
Re:Synapse e Domotica
« Risposta #21 il: Agosto 12, 2022, 03:14:42 pm »
non ti sei perso, hai capito tutto benissimo (le mie capacità comunicative non sono cosi pessime allora  ;D)

il thread 1 (la parte grafica del programma è il principale)
nella sezione public ho dichiarato

ArrInput:array of TInput;

Tinput è un record (dichiarato in una unit a parte solo per semplicità di gestione) ed è cosi dichiarato:

type
  TInput=record
    IndxDb,IndxArr,Numero,Timer,AnValoreAttuale,AnValMax,AnValMin,AnValIntervento,AnValCampionatura,
    IndxArrDispositivo,Utilizzo:Integer; //utilizzo corrisponde al'indice della corrispondente tabella nel db
    Etichetta,IcoON,IcoOFF,Suono,IPDispositivo:String;
    Invertito,Antifurto,Digitale:Boolean;
    IndxOutComandato:array of Integer; //inserire il numero del/degli output da comandare che corrisponde all'indice dell'array
    Stato:TStato;
  end;


il thread 2 (dedicato alla comunicazione con le schede) va ad aggiornare AnValoreAttuale e non si ferma altrimenti durante il movimento delle tapparelle non potrei accendere le luci (per esempio) ma ciò non accade

nel metodo execute (estrapolo qualche riga)

FR_Main.ArrInput[IOIndx].AnValoreAttuale:=Hex2Dec(StrElab[i+2]+StrElab[i+3]+StrElab+StrElab[i+1]);
(strElab è la stringa ricevuta ed elaborata-Fr_Main è la form del thread 1 )

if TImage(FR_Main.BCP_Pianta.FindComponent('InImg'+IntToStr(IOIndx)))<>Nil then //se l'immagine è sul BCP_Pianta
begin
  TImage(FR_Main.BCP_Pianta.FindComponent('InImg'+IntToStr(IOIndx))).Repaint;
end;

(qui aggiorno la form principale facendogli colorare la tapparella a livello grafico), se il record nell'array non venisse aggiornato il repaint non mi effettuerebbe il corretto repaint del "disegno" della tapparralle ma quello funziona

il thread 3 (che viene creato e distrutto solo al movimento della tapparella)

nel metodo execute (estrapolo qualche riga)


if FR_Main.ArrInput[IOIndx].AnValoreAttuale>=TapparellaPosizStop+FR_Main.ArrInput[IOIndx].AnValCampionatura)and
           (FR_Main.ArrInput[IOIndx].AnValoreAttuale<=TapparellaPosizStop-FR_Main.ArrInput[IOIndx].AnValCampionatura)then
           begin
             TapparellaStop(IndxFinestra);
           end;

qui USANDO IL DEBUG (effettivamente non ho provato ad usare edit o altro) il valore di FR_Main.ArrInput[IOIndx].AnValoreAttuale è sempre lo stesso identico e corrisponde
(faccio una prova con una edit per verificare che abbia lo stesso problema)
IOIndx mi riulta corretto sempre da debug

spero di avere risposto a tutto  ::)
grazie intanto



DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Synapse e Domotica
« Risposta #22 il: Agosto 12, 2022, 04:01:06 pm »
Ok, allora intanto un commento secco:

TUTTE LE PARTI LCL (SOPRATTUTTO LE COMPONENTI GRAFICHE E QUINDI TIMAGE INCLUSA) NON DEVONO IN ALCUN MODO ESSERE "TOCCATE" DA UN THREAD. ALMENO PER CIO' CHE E' DI MIA CONOSCENZA ... SAREI LIETO SE QUALCUNO MI CONTRADDICESSE.

QUESTO PERCHE' IN GENERALE I COMPONENTI GRAFICI NON SONO THREADSAFE.

NEL TUO CODICE, L'USO NEL THREAD della TIMAGE può generare di tutto (soprattutto problemi).

Ripartiamo da qui.

La dichiarazione ArrInput non appartiene ad un Thread ma alla tua FORM PRINCIPALE.

StrElab immagino sia una variabile globale, il cui formato viene assicurato e verificato: quando nel Thread 2 fai Hex2Dec(StrElab[i+2]
...." se ci sono caratteri diversi da quelli esadecimali il valore non viene aggiornato ovviamente perchè la funzione andrà in eccezione.

Fai molta attenzione a quello che fai: la StrElab che proviene da una elaborazione non è garantita che sia coerente quando la leggi nel THREAD 2 .... Ti faccio un esempio: se la StrElab la elabori da qualche parte e il THREAD 2 la và a leggere in maniere asincrona può essere che la StrElab sia ancora incompleta. Per fare si che la StrElab sia completa quando la leggi nel Thread 2 devi usare qualche tecnica di sincronizzazione (non ne parlo qui se no il post diventa illeggibile).

Stesso discorso vale per ArrInput: devi garantire la coerenza di TUTTI i dati interni e la sincronia (DURANTE LA SCRITTURA NESSUNO DEVE LEGGERLA, PENA UNA INCOERENZA).

Invece per quello che riguarda il debug, non sò dirti con precisione quanto sia affidabile quello di FPC, ma posso dirti che in MULTITHREADING tutti i debug che ho provato qualche problemino c'è l'avevano .... ANCHE x64DBG .....

Ciao
« Ultima modifica: Agosto 12, 2022, 04:20:54 pm da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

Diego1981

  • Full Member
  • ***
  • Post: 180
  • Karma: +0/-0
Re:Synapse e Domotica
« Risposta #23 il: Agosto 13, 2022, 08:57:00 am »
Ciao Drago
ero sicuro che mi avresti fatto notare la questione delle immagini nel thread esterno  ;D perchè ovviamente hai ragione e sicuramente sarà una di quelle cose che dovrò sistemare ma purtroppo per me sono tecniche che devo comprendere
StrElab come dici tu è una stringa che viene inviata dalla scheda degli input, ed ovviamente non avendoti riportato tutto il codice, non puoi sapere che faccio dei controlli sulla lunghezza  prima di elaborarla
Purtroppo da ieri non sono ancora riuscito a fare le prove che ti avevo detto ma anche io ho il dubbio che hai sollevato sulla questione della lettura e scrittura nel record ArrInput, quindi appena riesco a fare delle prove verifico
Per me che sono un "programmatore amatoriale autodidatta" certe cose sono difficili da compre e magari ne do molte per scontate che poi si rivelano l'opposto di quello che pensavo.
Giusto per avere un tuo parere, trovi corretto mettere gli array di record che "immagazzinano" i dati sullo stato degli I/O nella form principale o sarebbe meglio inserirli nel thread dove vengono elaborate le stringhe di invio e ricezione o anche da qualche altra parte?
So che forse sono domande difficili non sapendo come ho strutturato il programma ma ogni consiglio è ovviamente ben accetto
grazie

bonmario

  • Hero Member
  • *****
  • Post: 1300
  • Karma: +10/-1
Re:Synapse e Domotica
« Risposta #24 il: Agosto 13, 2022, 10:14:08 am »
TUTTE LE PARTI LCL (SOPRATTUTTO LE COMPONENTI GRAFICHE E QUINDI TIMAGE INCLUSA) NON DEVONO IN ALCUN MODO ESSERE "TOCCATE" DA UN THREAD. ALMENO PER CIO' CHE E' DI MIA CONOSCENZA ... SAREI LIETO SE QUALCUNO MI CONTRADDICESSE.

QUESTO PERCHE' IN GENERALE I COMPONENTI GRAFICI NON SONO THREADSAFE.

Scusa, magari ho capito male io, ma io non mi sono mai fatto problemi ad usarle. Certo, lo faccio usando le "Critical section", per evitare problemi, ma lo faccio !

Ciao, Mario

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Synapse e Domotica
« Risposta #25 il: Agosto 13, 2022, 10:58:43 am »
TUTTE LE PARTI LCL (SOPRATTUTTO LE COMPONENTI GRAFICHE E QUINDI TIMAGE INCLUSA) NON DEVONO IN ALCUN MODO ESSERE "TOCCATE" DA UN THREAD. ALMENO PER CIO' CHE E' DI MIA CONOSCENZA ... SAREI LIETO SE QUALCUNO MI CONTRADDICESSE.
QUESTO PERCHE' IN GENERALE I COMPONENTI GRAFICI NON SONO THREADSAFE.
Scusa, magari ho capito male io, ma io non mi sono mai fatto problemi ad usarle. Certo, lo faccio usando le "Critical section", per evitare problemi, ma lo faccio !
Ciao, Mario

Per tutte le parti grafiche, e in generali per tutti i componenti LCL l'uso nei Thread non è consentito. L'uso delle "Crtical Section" quando fai ad esempio una operazione su una parte grafica (Form ad esempio) non ha alcun senso, visto che non può essere garantito che l'accesso alle risorse avvenga solo nella TUA Critical Section.

In generale, affinchè una qualsiasi risorsa (le più critiche sono appunto le risorse grafiche) sia protetta ha necessità di avere delle barriere PER TUTTI gli accessi che avvengano alla risorsa. Se tutti accedono tramite la stessa barriera tutto va bene, se viene effettuato anche solo un accesso senza la barriera (è ciò che accade nelle LCL) allora è assolutamente inutile usare semafori, critical section, mutex o altro.

E' per questo che non c'è soluzione all'uso delle parti grafiche nei Thread. In realtà si può usare la procedura SYNCHRONIZE dei Thread che consente di eseguire una parte del codice del Thread nel THREAD PRINCIPALE, dove è sicuro eseguire qualsiasi cosa ... sempre con le dovute accortezze ....

Ultimamente negli ambienti più moderni è possibile eseguire alcune operazioni grafiche, le più comuni, nei Thread in quanto alcuni componenti hanno incapsulato delle barriere "automatiche" all'accesso e quindi non c'è necessità che l'utente vi provveda.
NON PENSO che ciò sia stato fatto nelle LCL. Inoltre le accortezze di cui sopra possono provocare degli effetti "secondari" di non poco conto. Supponiamo che i componenti abbiano una protezione automatica, significa che se un Thread "entra" e la barriera è attiva  ... il Thread si BLOCCA sino a quando la barriera non si disattiva. E per le parti grafiche ciò vuol dire tanto tempo (alle volte decine di millisecondi).

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Synapse e Domotica
« Risposta #26 il: Agosto 13, 2022, 11:16:37 am »
Giusto per avere un tuo parere, trovi corretto mettere gli array di record che "immagazzinano" i dati sullo stato degli I/O nella form principale o sarebbe meglio inserirli nel thread dove vengono elaborate le stringhe di invio e ricezione o anche da qualche altra parte?
So che forse sono domande difficili non sapendo come ho strutturato il programma ma ogni consiglio è ovviamente ben accetto
grazie

In generale la "disposizione delle risorse", inteso come vengono allocate e dove, dipende da diversi fattori. Nei sistemi dove le prestazioni devono essere estremizzate c'è anche una analisi delle allocazioni (HEAP, STACK, MEMORIA VIRTUALE, etc....) con relativo calcolo delle prestazioni di accesso.

In generale comunque si deve cercare di creare risorse il cui accesso soprattutto se condiviso, sia facilmente gestibile. Normalmente si creano classi o record "avanzati" dove vengono incapsulati gli accessi con le proprietà, in cui puoi già inserire una barriera di protezione (un semaforo o una critical section ad esempio). Il tuo array sarò privato (o strettamente privato) e l'accesso potrà avvenire solo dalle proprietà esposte.

Nel tuo caso vedrei un record avanzato definito globalmente e non membro di una Form perchè in quest'ultimo caso tieni presente che il tuo codice deve eseguire un accesso alla Form se deve usare l'array e inoltre la Form dovrà essere indicata in tutte le unità che la usano (in generale una unità dove è definito un Thread non dovrebbe avere niente a che fare con Form e altri classi grafiche).

Per i record avanzati, ti rimando al capitolo apposito: https://wiki.freepascal.org/Record

Se hai necessità ti posso postare anche un piccolo codice.

Attendiamo news.

Ciao
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

Diego1981

  • Full Member
  • ***
  • Post: 180
  • Karma: +0/-0
Re:Synapse e Domotica
« Risposta #27 il: Agosto 13, 2022, 01:32:26 pm »
cavoli non sapevo si potessero utilizzare i record in questo modo

grazie

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1266
  • Karma: +43/-0
  • Prima ascoltare, poi decidere
Re:Synapse e Domotica
« Risposta #28 il: Agosto 13, 2022, 04:18:31 pm »
Se vuoi, qui c'è un codice che puoi usare come partenza ..... Semplicemente Crea una applicazione, poi inserisci un pulsante nella form, doppio click sia sul pulsante che sulla form e poi copia tutto il codice qui elencato (o copia a pezzi, come ritieni più opportuno).

Codice: [Seleziona]
unit Unit1;

{$mode objfpc}{$H+}
{$modeswitch advancedrecords}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;


const
  MAX_TAPPARELLE = 13;

type
  TInput=record
    IndxDb,IndxArr,Numero,Timer,AnValoreAttuale,AnValMax,AnValMin,AnValIntervento,AnValCampionatura,
    IndxArrDispositivo,Utilizzo:Integer; //utilizzo corrisponde al'indice della corrispondente tabella nel db
    Etichetta,IcoON,IcoOFF,Suono,IPDispositivo:String;
    Invertito,Antifurto,Digitale:Boolean;
    IndxOutComandato:array of Integer; //inserire il numero del/degli output da comandare che corrisponde all'indice dell'array
    Stato: TStato;
  end;

type
  TDati_Tap = record
    strict private ArrInput:array of TInput;
    function getArrayInput(Index: cardinal): TInput;
    procedure setArrayInput( Index: cardinal; Value: TInput);
  private
    class operator Initialize (var Dest: TDati_Tap);
    class operator Finalize (var Dest: TDati_Tap);
  public
    property Tappa[Index: cardinal]: TInput read getArrayInput write setArrayInput;
end;

type
  EDATITAPPARELLEINVALID = class(Exception);

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private

  public

  end;

var
  Form1: TForm1;
  Tapparelle: TDati_Tap;

implementation

{$R *.lfm}

{ TForm1 }

class operator TDati_Tap.Initialize (var Dest: TDati_Tap);
var i: cardinal;
begin
  SetLength(Dest.ArrInput, MAX_TAPPARELLE);
  //Qui puoi inizializzare tutti i valori dell'array
  for i:= Low(Dest.ArrInput) to High(Dest.ArrInput) do
    begin
      Dest.ArrInput[i].IndxDb:= 0;
      //etc .....
    end;
end;

class operator TDati_Tap.Finalize (var Dest: TDati_Tap);
begin
  SetLength(Dest.ArrInput, 0);
end;

function TDati_Tap.getArrayInput(Index: cardinal): TInput;
begin
  if (Index >= Low(ArrInput)) and (Index <= High(ArrInput)) then
    begin
      Result := ArrInput[Index];
    end
  else
    raise EDATITAPPARELLEINVALID.Create('Richiesta al di fuori dei limiti');
end;

procedure TDati_Tap.setArrayInput(Index: cardinal; Value: TInput);
begin
  if (Index >= Low(ArrInput)) and (Index < High(ArrInput)) then
    begin
      ArrInput[Index] := Value;
    end
  else
    raise EDATITAPPARELLEINVALID.Create('Richiesta al di fuori dei limiti');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(Tapparelle.Tappa[0].IndxDb.toString);
end;

procedure TForm1.FormCreate(Sender: TObject);
var prova: TInput;
begin
  Prova.IndxDb := 20;
  //Prova.Antifurto:= ....;
  //etc ....
  Tapparelle.Tappa[0] := Prova;
end;

end.

P.S.: Non ti ho inserito barriere di protezione, è solo per darti un là su un altro modo di gestire i dati.

Ciao
« Ultima modifica: Agosto 13, 2022, 04:37:37 pm da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

Diego1981

  • Full Member
  • ***
  • Post: 180
  • Karma: +0/-0
Re:Synapse e Domotica
« Risposta #29 il: Agosto 13, 2022, 05:56:41 pm »
Grazie Drago
provo a "tradurre" il tuo programma  :o ;D

sono riuscito a controllare e ti confermo che è il debug a non funzionare
Ho messo delle label e quelle si aggiornavano correttamente

credi che 13 thread non diano problemi al pc in merito alle prestazione?

 

Recenti

How To

Utenti
  • Utenti in totale: 785
  • Latest: gmax
Stats
  • Post in totale: 18771
  • Topic in totale: 2233
  • Online Today: 321
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 0
Guests: 321
Total: 321

Disclaimer:

Questo blog non rappresenta una testata giornalistica poiché viene aggiornato senza alcuna periodicità. Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n. 62/2001.