Comunicazione tra macchine a stati con transizioni nascoste

3

La questione è emersa per me nella programmazione embedded, ma penso che possa essere applicata a un certo numero di situazioni di rete generale, ad es. quando un partner di comunicazione fallisce.

Supponiamo di avere una logica di applicazione (un programma) in esecuzione su un computer e un gadget collegato a quel computer tramite ad es. un'interfaccia seriale come RS232. Il gadget ha un LED rosso / verde / blu e un pulsante che disabilita il LED. Il colore dei LED può essere guidato da comandi software sull'interfaccia seriale e lo stato (rosso / verde / blu / spento) viene riletto e provoca una reazione nella logica dell'applicazione. Il comportamento asincrono della logica dell'applicazione in relazione al colore del LED fino a un certo ritardo (a seconda del ciclo di esecuzione dell'applicazione) è tollerato.

Ciò che essenzialmente abbiamo è una risorsa (il LED) che non può essere riservata e gestita atomicamente dal software perché l'utente (organico) può in qualsiasi momento premere il pulsante per interferire / interrompere il tentativo del software di cambiare il colore del LED.

Spogliamo questo esempio dal suo equipaggiamento fisico oso dire che abbiamo due macchine a stati comunicanti A (logica applicativa) e G (gadget) dove G esegue cambiamenti di stato all'insaputa di A (e anche il contrario, ma questo è non significativo nel nostro esempio) e solo A può essere modificato ad un prezzo ragionevole. A ha bisogno di vedere la reazione e lo stato di G in un'informazione che può essere (leggermente) superata ma non incoerente rispetto alla finestra temporale breve quando questa informazione è stata generata sul lato di G.

Quello che sto cercando è un metodo conciso per gestire una situazione del genere nel software embedded (ad esempio non sono disponibili layer / framework come CORBA ecc.). Una tecnica di programmazione che è in grado di mappare il comportamento completo di entrambi i partecipanti su interfacce classiche di un linguaggio di programmazione classico (C in questo caso). Per complicare le cose (o meglio, per generalizzare), un semplice ciclo di comunicazione ad alta frequenza da A a G e ritorno (IOW: A sta rapidamente interrogando G) è fuori fuoco a causa di restrizioni tecniche (ritardo della comunicazione seriale, A non sempre attivo , eccetera.). Quello che attualmente vedo come una soluzione generale è:

  • la logica dell'applicazione A come un thread di esecuzione
  • un oggetto adattatore (proxy) PG (che presenta G all'interno del computer), insieme al driver seriale come un altro thread
  • un oggetto di comunicazione tra i due (A e PG) che è scambiabile in modo sicuro per transazioni

I due contesti di esecuzione (thread) sul computer possono essere multi-core o solo interrupt o attività in un RTOS. L'oggetto com contiene i seguenti dati:

  • stato sospetto (scritto da A): efficacemente un membro del gruppo di stati di potere in G (nel nostro caso: rosso, verde, blu, spento, rosso_o_verde, rosso_o_bluè, rosso_o_off ... ecc.)
  • dati di comando (scritti da A): test_if_off, switch_to_red, switch_to_green, switch_to_blue
  • stato operativo (scritto da PG): operation_pending, success, wrong_state, link_broken
  • nuovo stato (scritto da PG): rosso, verde, blu, spento

L'idea dell'oggetto com è che A scriva qualsiasi (set di) stato in cui pensa che G sia, insieme a un comando. (Esempio: stato sospetto="red_or_green", comando: "switch_to_blue") Si noti che i comandi emessi da A non funzioneranno se l'utente ha spento il LED e A deve saperlo. PG raccoglierà un oggetto com e tenterà di inviare il comando a G, ricevere la sua risposta (o un timeout) e impostare lo stato dell'operazione e il nuovo stato di conseguenza. A riprenderà l'oject una volta che non è più in operation_pending e può reagire al risultato. Ovviamente l'oggetto com può essere separato (in due oggetti, uno per ciascuna direzione) ma penso che in quasi tutte le istanze sia conveniente avere il comando vicino al risultato.

Mi piacerebbe che venissero evidenziate grandi imperfezioni o che ascoltassi una visione completamente diversa su tale situazione.

    
posta slartibartfast 13.06.2012 - 15:35
fonte

2 risposte

2

Le transizioni nascoste e la latenza rendono questo un problema piuttosto interessante, soprattutto perché non è possibile modificare il gadget. È possibile che si stia cercando una sequenza di sincronizzazione o una sequenza di homing. ("Sincronizzazione" significa che puoi impartire una sequenza di comandi ed essere sicuro dello stato della macchina dello stato di destinazione quando hai finito. "Homing" significa che puoi impartire qualche sequenza di comandi, quindi verificare lo stato esaminando il uscita della macchina a stati).

Sven Sandberg ha una buona carta che mostra che (per qualsiasi macchina Mealy ben definita) puoi sempre costruire questi due tipi di sequenze. È tutta teoria, nessun codice, quindi dovrai fare qualche implementazione. Ecco il riferimento citeseer alla carta stessa e un slideshow Pdf delle idee.

Nel caso che descrivi, la latenza è ancora un problema. Sono curioso di sapere se hai qualche idea del margine di errore su questi cambiamenti di stato "nascosto". Quanto tempo tra loro? Sono più comuni o più frequenti, in alcuni casi rispetto ad altri? Le risposte a queste domande possono aiutarti a definire queste sequenze di controllo.

    
risposta data 30.06.2012 - 01:20
fonte
0

A meno che tu non possa effettivamente impedire che il pulsante venga premuto sull'applicazione, avrai sempre una finestra aperta affinché il gadget abbia lo stato modificato tra i messaggi di controllo. Questa finestra esisterà sempre se non hai i mezzi per applicare un semaforo tra le operazioni A e G.

    
risposta data 19.06.2012 - 23:47
fonte