Il presente articolo è stato tradotto automaticamente.

Robotics

Scrittura e test di servizi VPL per comunicazioni seriali

Trevor Taylor

Microsoft Robotics Developer Studio (RDS) è, come prevedibile, una piattaforma per la programmazione di robot. RDS fornito nel 2006 e la versione più recente RDS 2008 R2, è stata rilasciata nel giugno 2009.

RDS è costituito da quattro componenti principali: la concorrenza e Coordination Runtime (CCR) Decentralized Software Services (DSS), Visual Programming Language (VPL) e Visual Simulation Environment (VSE). Sara Morgan parlato VSE nel numero di giugno 2008 di MSDN Magazine (informazioni in lingua inglese) (MSDN.Microsoft.com/magazine/cc546547).

VPL, tuttavia, è più pertinente per questo articolo. VPL è un linguaggio di flusso dei dati, che significa che è possibile creare programmi disegnando diagrammi sullo schermo. In fase di esecuzione, i messaggi si spostano da un blocco a altro nel diagramma e il flusso dei dati è in realtà il percorso di esecuzione del programma. Poiché VPL si basa su CCR e DSS, dataflows può verificarsi in modo asincrono (di conseguenza le notifiche dai servizi) e può anche essere eseguito in parallelo. Mentre VPL è destinato ai programmatori principianti, programmatori esperti possono inoltre essere utile per la creazione di prototipi.

In questo articolo viene illustrato un semplice servizio RDS, che consente di inviare e ricevere i dati utilizzando una porta seriale (noto anche come una porta COM). Nell'esempio di codice vengono illustrati alcuni concetti coinvolti nella scrittura di servizi riutilizzabile RDS.

Per ulteriori informazioni su RDS e scaricare la piattaforma, passare microsoft.com/robotics. Il pacchetto include un file della Guida utile, è disponibile anche al msdn.microsoft.com/library/dd936006. È possibile ottenere ulteriore assistenza registrando le domande ai forum di discussione Robotics vari in social.msdn.Microsoft.com/Forums/en-us/Category/Robotics.

Servizi RDS

RDS servizi sono stati creati utilizzando CCR e DSS. Sono concettualmente simili ai servizi Web in quanto RDS ha un'architettura orientata ai servizi (SOA) basata su un modello di REST (Representational State Transfer) utilizzando DSSP (Decentralized Software Services Protocol) per la comunicazione tra i servizi. Wading attraverso tutti questo soup dell'alfabeto, ciò significa che non interfacciarsi direttamente con servizi di RDS. In alternativa, è possibile inviare messaggi a un proxy che funge da interfaccia esterna del servizio (agli sviluppatori Web un approccio avere familiarità con). Significa inoltre che servizi possono essere distribuiti in qualsiasi punto della rete.

L'utilizzo di un proxy ha due effetti. Innanzitutto, i messaggi inviati tra i servizi prima della trasmissione serializzati e deserializzati a altra estremità. XML è il formato normale per i dati trasmessi. In secondo luogo, il proxy definisce un contratto, in modo efficace il set di API che sono esposti ad altri servizi.

Ogni servizio dispone di uno stato interno, che è possibile recuperare o modificare le operazioni del servizio. Questi implicano l'invio di un messaggio di richiesta e in attesa di un messaggio di risposta in un processo simile a quella utilizzata dalla maggior parte dei servizi Web.

Quando viene modificato lo stato del servizio, può inviare notifiche ai sottoscrittori. Questo approccio pubblicazione e sottoscrizione rende RDS servizi diversi da servizi Web tradizionali poiché i messaggi di notifica vengono inviati in modo asincrono ai sottoscrittori.

Quando si genera un nuovo servizio, diventa automaticamente visibile in VPL e iniziare a utilizzare immediatamente. Si tratta di una delle principali funzionalità RDS e rende test e la creazione di prototipi molto semplice, ovvero si Don ’t necessario scrivere test harness C#, perché è invece possibile utilizzare VPL.

Controllare un robot remota

Molti robot didattici semplice disporre microcontroller 8 o 16 bit per il cervello su scheda. Ma poiché RDS viene eseguito su Windows in .NET Framework, non genera codice che può essere eseguito direttamente su tali robot. Deve essere controllate in remoto tramite un collegamento di comunicazione invece. (L'alternativa è disporre di un PC su scheda, ad esempio 3DX MobileRobots Pioneer).

Poiché la maggior parte delle microcontroller supporto porte seriali, una connessione seriale è la soluzione più ovvia. Tuttavia, non fornisce il collegamento utilizzando un cavo è ideale, ma limita mobilità del robot.

In alternativa, è possibile utilizzare per creare una connessione senza fili installando una periferica seriale su Bluetooth nel robot Bluetooth. Vengono forniti alcuni robot, ad esempio NXT LEGO, con Bluetooth incorporata. Altri, quali RoboticsConnection Stinger, disporre i moduli facoltativi Bluetooth. Bluetooth è una buona scelta, dato che è standard nella maggior parte dei computer portatili questi giorni. Anche se il computer non dispone di Bluetooth, troverete economici, siano immediatamente disponibili periferiche USB Bluetooth.

La buona notizia è che si Don ’t necessario conoscere il linguaggio di programmazione Bluetooth perché la connessione per il robot apparirà come una porta seriale virtuale. È possibile utilizzare lo stesso codice come se un cavo fisico che sono stati fornisce la connessione seriale. L'unica differenza è che è necessario stabilire un abbinamento tra il PC e il dispositivo sul robot in modo che una porta COM virtuale verrà creata.

Alcune schede di controllo robot dispongono di firmware che è in grado di accettare i comandi mediante un linguaggio semplice comando. Con il serializzatore da RoboticsConnection (che ottiene il nome dall'uso di un protocollo seriale), ad esempio, è possibile digitare i comandi per il controller tramite un programma terminale come HyperTerminal. I comandi sono tutto leggibili e terminare ogni premendo Immettere.

Se si sta progettando il proprio protocollo per l'utilizzo con un robot, è necessario effettuare alcune scelte. Innanzitutto, è necessario decidere se è necessario inviare dati binari. Conversione di valori binari in esadecimale o decimale per la trasmissione richiede maggiore larghezza di banda e aumenta l'elaborazione sovraccarico per la CPU su scheda. D'altra parte, consente la lettura dei messaggi molto più semplici e non si verifica qualsiasi comportamento anomalo a causa di caratteri di controllo misinterpreted.

La domanda successiva è se si desidera utilizzare i pacchetti a lunghezza fissa o in un formato a lunghezza variabile più flessibile. Lunghezza fissa è più semplice analizzare e i risultati migliori con formato esadecimale.

È consigliabile se si utilizzerà un checksum. Per le comunicazioni da computer a computer il calcolo delle cifre di controllo sono semplice. Se tuttavia si desidera verificare il vostro robot digitando i comandi manualmente, ottiene molto difficile capire le cifre di controllo. Quando si utilizzano i valori di checksum, typically il destinatario invia nuovamente un riconoscimento (ACK) o di riconoscimento (NAK) a seconda se il comando fornita correttamente o non. La decisione sull'utilizzo di un checksum proviene realmente verso il basso per l'affidabilità della connessione.

Il servizio SerialPort

Dovrebbe essere evidente dall'ora perché un servizio porta seriale potrebbe essere utile. Il pacchetto RDS, tuttavia, non include un servizio anche se molti degli esempi di robot utilizzano collegamenti di comunicazione seriale. Se si Esplora il codice di esempio RDS, sono disponibili in ogni esempio di gestisce la porta seriale in modo diverso. In questo articolo viene descritto un approccio all'utilizzo di una porta seriale. Non è l'unico modo per farlo, non necessariamente il modo migliore.

Prima di procedere qualsiasi, assicurarsi che è stato scaricato e installato RDS. Download di questo articolo contiene codice sorgente del servizio SerialPort. Decomprimerlo in una cartella nella directory di installazione RDS (noto anche come punto di montaggio). Nota il codice deve mantenere separati dalla cartella degli esempi viene fornito con RDS in modo che si Don ’t contengano una combinazione di codice con il codice Microsoft. Inoltre, è consigliabile inserire il codice sotto il punto di montaggio RDS anziché in un' posizione sul disco rigido, perché semplifica lo sviluppo. Dispone di una cartella di progetti in cui si mantiene tutto il mio codice nelle sottocartelle, consentendo di eseguire il backup.

I file principali nel codice sorgente SerialPort sono SerialPort.cs, SerialPortTypes.cs e SerialPort.manifest.xml.

SerialPort.cs contiene l'implementazione del servizio o il comportamento. Costituito della classe del servizio, che contiene i gestori di operazione, inoltre, qualsiasi richiesta supporta i metodi e le variabili.

SerialPortTypes.cs contiene le definizioni dello stato del servizio, i tipi di operazioni e i tipi di messaggio. In effetti, che descrive l'interfaccia per il servizio e non deve contenere codice eseguibile. Si tratta di un punto chiave su un contratto di servizio, è solo una definizione di dati.

SerialPort.manifest.xml viene chiamato il manifesto e viene descritto come combinare, o servizi coordinati per l'esecuzione di un'applicazione. Questo file viene utilizzato come input per l'utilità DssHost, che crea un nodo DSS servizi vengono eseguiti all'interno. In questo caso il manifesto viene eseguito solo il servizio SerialPort, che è piuttosto inutile. Un manifesto utile specificare anche altri servizi si basano sul servizio SerialPort per effettuare connessioni.

Prima di utilizzare il servizio SerialPort, è necessario eseguire lo strumento DssProjectMigration e quindi ricompilare il servizio. Aprire un prompt dei comandi di DSS (aspetto in RDS dal menu di avvio) e assicurarsi che i percorsi impostati in modo da poter eseguire i file nella cartella \bin. Quindi passare alla directory in cui decompressa il codice e immettere il seguente comando:

Dssprojectmigration /b- .

Indica che il /b-option Don ’t creare una copia di backup e il carattere punto (.) si riferisce alla directory corrente.

È possibile compilare il servizio in Visual Studio o farlo dalla riga di comando digitando:

Msbuild serialport.sln

Il servizio di compilazione genera la DLL del servizio, una DLL proxy e una trasformazione DLL (che converte i tipi di dati tra la DLL del servizio e il proxy). Questi vengono tutti inseriti nella cartella \bin sotto il punto di montaggio RDS. È opportuno lasciare i file manifesto e di configurazione tra loro tramite la copia nella cartella \Esempi\config (anche se non è essenziale).

Il contratto di assistenza

Ogni servizio dispone di un identificatore univoco del contratto, che viene dichiarato nel file Types.cs che assomiglia a un URL. Si noti tuttavia che esso è irrilevante sul Web e tramite un identificatore di formato URL è semplicemente un modo pratico per garantire l'univocità, consentendo alle organizzazioni di creare propri spazi dei nomi. (Per i progetti sarà necessario utilizzare uno spazio dei nomi diverso microsoft.com/robotics.) SerialPortTypes.cs contiene la seguente definizione:

public sealed class Contract {
  [DataMember]
  public const string Identifier = "http://www.promrds.com/contracts/2009/12/serialport.html";
}

Un contratto comprende anche lo stato e le operazioni che definiscono le proprietà che possono manipolare altri servizi e le modalità. SerialPortState (vedere Nella figura 1) include la configurazione della porta seriale, alcuni parametri per i timeout e dell'ultimo byte ricevute in modo asincrono.

Figura 1 SerialPortState

[DataContract]
public class SerialPortState {
  private bool _openOnStart;
  private bool _asynchronous;
  private SerialPortConfig _config;
  private byte _lastByteReceived;
  private bool _isOpen;

  // Open the COM port when the service starts
  // Must be set in config file
  [DataMember]
  public bool OpenOnStart {
    get { return _openOnStart; }
    set { _openOnStart = value; }
  }

  // Operate in Asynchronous mode 
  [DataMember]
  public bool Asynchronous {
    get { return _asynchronous; }
    set { _asynchronous = value; }
  }

  // Configuration parameters for the serial port
  [DataMember]
  public SerialPortConfig Config {
    get { return _config; }
    set { _config = value; }
  }

  // Last byte received from the serial port
  [DataMember]
  public byte LastByteReceived {
    get { return _lastByteReceived; }
     set { _lastByteReceived = value; }
  }

  // Indicates if the port is currently open
  [DataMember]
  public bool IsOpen {
    get { return _isOpen; }
    set { _isOpen = value; }
  }
}

È possibile definire tipi di dati personalizzati per l'utilizzo dei tipi di stato e il messaggio. In questo servizio è una classe SerialPortConfig. Per rendere visibili nel proxy, deve essere pubblico e contrassegnato con l'attributo [DataContract]. Ciascuna proprietà della classe deve essere dichiarato public e inoltre essere contrassegnati con l'attributo [DataMember]. Se questa operazione non viene eseguita, la proprietà non sarà accessibile.

È anche possibile esporre gli enum pubblici, ovvero in questo modo altri programmatori non più necessario utilizzare numeri magia nel codice che utilizza il servizio. È buona norma troppo, programmazione perché consente di controllare il tipo di dati.

Quando si progetta un servizio, è necessario decidere la modalità di interazione con altri servizi. Questo servizio SerialPort supporta le operazioni seguenti, elencate di seguito in gruppi logici:

  • Ottenere, sottoscrizione
  • ReceiveByte
  • SetConfig, Open, Close, ClearBuffers
  • ReadString ReadByte ReadByteArray,
  • WriteString WriteByte WriteByteArray,

Si noti che l'operazione ReceiveByte è per uso interno per il servizio stesso e non dovrebbe essere utilizzato da altri servizi. Ne parleremo più avanti.

Le operazioni di lettura e scrittura sono tutti sincrone, ovvero il servizio non risponde fino al completamento dell'operazione. Se si apre la porta seriale in modalità asincrona (descritto di seguito), il servizio invierà una notifica ReceiveByte per ogni byte ricevuto e si consiglia di non utilizzare le operazioni di lettura. Le operazioni di scrittura, tuttavia, sono sempre sincrone.

Ogni operazione dispone di un tipo di messaggio di richiesta e un tipo di messaggio di risposta. Alcuni di questi potrebbero disporre di proprietà e gli altri utenti saranno vuoti, ovvero il tipo di dati è sufficiente per trasmettere il messaggio appropriato.

Comportamento servizio

Come osservato in precedenza, il codice eseguibile del servizio è in SerialPort.cs. Tutti i servizi sono derivati da DsspServiceBase, sono disponibili numerose proprietà e metodi di supporto. Quando un servizio viene avviato, viene chiamato il relativo metodo di avvio:

protected override void Start() {
  InitializeState();
  base.Start();
  if (_state.OpenOnStart)
    OpenPort();
}

Inizio si occupa di inizializzazione dello stato (se necessario) e l'apertura della porta seriale automaticamente se OpenOnStart è stato specificato nel file di configurazione (descritto di seguito).

Ogni operazione supportata da un servizio deve avere un gestore del servizio. Ma vengono gestiti dall'infrastruttura di alcune operazioni, ad esempio Get e la selezione (a meno che non si desidera eseguire l'override del comportamento predefinito).

Il OpenHandler viene illustrato un gestore molto semplice:

[ServiceHandler]
public void OpenHandler(Open open) {
  // Remember the Asynchronous flag
  _state.Asynchronous = open.Body.Asynchronous;
  if (OpenPort()) {
    open.ResponsePort.Post(
      DefaultSubmitResponseType.Instance);
  }
  else {
    throw (new Exception(“Open Failed”));
  }
}

Questo gestore chiama OpenPort, un metodo interno. Se questo ha esito positivo, verrà registrata nuovamente una risposta. Poiché non dispone di informazioni deve essere restituito, questo è solo una risposta predefinita fornita da DSS.

Se l'apertura ha esito negativo, viene generata un'eccezione. DSS intercetta l'eccezione e lo converte in un errore, viene inviato come risposta. Anche se non immediatamente evidente, se si verifica un'eccezione in OpenPort, verrà inoltre propagati fino e restituire un errore.

Non è necessario spiegare tutte metodo OpenPort, ma un punto è importante, è possibile aprire la porta seriale per l'operazione sincrona o asincrona. In modalità sincrona, tutte le richieste di lettura e scrittura completare prima di restituire una risposta. Tuttavia, se si apre in modalità asincrona, le notifiche vengono inviate per ogni carattere ricevuto. Per rendere questo lavoro, il codice imposta un gestore eventi convenzionale:

if (_state.Asynchronous) {
  // Set up an Event Handler for received characters
  sp.ReceivedBytesThreshold = 1;
  sp.DataReceived += new SerialDataReceivedEventHandler(
    DataReceivedHandler);
}

Il gestore eventi viene visualizzato in Nella figura 2. Questo gestore viene eseguito su un thread. NET. Ma per l'interoperabilità con DSS, è necessario quale passare un thread CCR, in modo che il codice invia una richiesta ReceiveByte alla porta operazioni principali del servizio. Dopo una richiesta di registrazione, il codice deve ricevere la risposta; in caso contrario vi sarà una perdita di memoria. Questo è lo scopo di Arbiter.Choice, viene utilizzata la notazione abbreviata C# per delegati anonimi per gestire due possibili risposte. È necessario collocare il ricevitore scelta in coda attiva un'attivazione. In questo caso solo un errore è pertinente e un risultato positivo non esegue alcuna operazione.

Nella figura 2 Gestore evento

void DataReceivedHandler(object sender, 
  SerialDataReceivedEventArgs e) {

  int data;
  while (sp.BytesToRead > 0) {
    // Read a byte - this will return immediately because
    // we know that there is data available
    data = sp.ReadByte();
    // Post the byte to our own main port so that
    // notifications will be sent out
    ReceiveByte rb = new ReceiveByte();
    rb.Body.Data = (byte)data;
    _mainPort.Post(rb);
    Activate(Arbiter.Choice(rb.ResponsePort,
      success => { },
      fault => { LogError("ReceiveByte failed"); }
      ));
  }
}

Il gestore ReceiveByte verrà eseguito per elaborare il nuovo carattere:

[ServiceHandler]
public void ReceiveByteHandler(ReceiveByte recv) {
  _state.LastByteReceived = recv.Body.Data;
  // Send a notification, but only if in asynch mode
  if (_state.Asynchronous)
    SendNotification(_submgrPort, recv);
  recv.ResponsePort.Post(DefaultUpdateResponseType.Instance);
}

L'attributo [DmServer] DSS è possibile associare il gestore alla porta operazioni durante l'inizializzazione del servizio. Il gestore invia una notifica ai sottoscrittori, quindi il postback di una risposta che indica che l'operazione viene completata. (I servizi che si desiderano ricevere notifiche devono inviare un'operazione di sottoscrizione al servizio SerialPort).

Leggere i gestori di servizio per l'altro e le operazioni di scrittura sono abbastanza facile interpretazione. Il WriteStringHandler (vedere Nella figura 3) contiene una ruga piccola, tuttavia, è possibile inserire un lieve ritardo tra l'invio di caratteri. Questo è stato progettato per semplificare microcontroller lenta potrebbe non essere in grado di tenere il passo se i dati vengono inviati alla massima velocità, periferiche di especially quali il BasicStamp bit banging e Don ’t hanno un hardware UART Universal Asynchronous Receiver/Transmitter (), quindi eseguire I/O seriale nel software.

Nella figura 3 WriteStringHandler

[ServiceHandler]
public virtual IEnumerator<ITask> WriteStringHandler(
  WriteString write) {

  if (!_state.IsOpen) {
    throw (new Exception("Port not open"));
  }

  // Check the parameters - An empty string is valid, but not null
  if (write.Body.DataString == null)
    throw (new Exception("Invalid Parameters"));

  // NOTE: This might hang forever if the comms link is broken
  // and you have not set a timeout. On the other hand, if there
  // is a timeout then an exception will be raised which is
  // handled automatically by DSS and returned as a Fault.
  if (_state.Config.InterCharacterDelay > 0) {
    byte[] data = new byte[1];
    for (int i = 0; i < write.Body.DataString.Length; i++) {
      data[0] = (byte)write.Body.DataString[i];
      sp.Write(data, 0, 1);
      yield return Timeout(_state.Config.InterCharacterDelay);
    }
    sp.WriteLine("");
  }
  else
    sp.WriteLine(write.Body.DataString);

  // Send back an acknowledgement now that the data is sent
  write.ResponsePort.Post(DefaultSubmitResponseType.Instance);
  yield break;
}

Un altro punto su questo gestore è che si tratta di un iteratore. Si noti la dichiarazione del metodo come IEnumerator <itask>e restituire il fatto che viene utilizzato yield e yield break. Questa funzionalità del linguaggio C# consente di CCR sospendere l'attività senza bloccare un thread. Quando viene eseguito yield return, il thread che esegue il metodo viene restituito al pool. Una volta completato il timeout, invia nuovamente un messaggio che causa l'esecuzione del ripristino, anche se probabilmente su un thread diverso.

Configurazione del servizio

Un file di configurazione è una versione serializzato XML dello stato del servizio viene caricato durante l'inizializzazione del servizio. È buona norma per supportare un file di configurazione perché consente di modificare il comportamento del servizio senza dover ricompilare. Ciò è particolarmente importante per impostare il numero della porta COM.

È possibile specificare il nome del file del servizio quando si dichiara l'istanza di stato (in SerialPort.cs):

[ServiceState]
// Add an initial state partner to read the config file
[InitialStatePartner(Optional = true, 
  ServiceUri = "SerialPort.Config.xml")]
SerialPortState _state = new SerialPortState();

In questo caso è stato dichiarato config come facoltativi; in caso contrario, il servizio non viene avviato se il file di configurazione è manca. D'altra parte, pertanto che è necessario controllare lo stato del metodo di avvio del servizio e inizializzare alcune impostazioni predefinite ragionevoli se necessario.

Poiché non viene specificato alcun percorso per il ServiceUri, DSS presupporrà che il file sia nella stessa cartella del manifesto utilizzato per avviare il servizio. Nella figura 4 viene illustrato il contenuto di un file di configurazione tipica.

Nella figura 4 File di configurazione per SerialPortState

<?xml version="1.0" encoding="utf-8"?>
<SerialPortState 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns=http://www.promrds.com/contracts/2009/12/serialport.html
  >
  <OpenOnStart>false</OpenOnStart>
  <Asynchronous>false</Asynchronous>
  <Config>
    <PortNumber>1</PortNumber>
    <BaudRate>57600</BaudRate>
    <Parity>None</Parity>
    <DataBits>8</DataBits>
    <StopBits>One</StopBits>
    <ReadTimeout>0</ReadTimeout>
    <WriteTimeout>0</WriteTimeout>
    <InterCharacterDelay>0</InterCharacterDelay>
  </Config>
  <LastByteReceived>0</LastByteReceived>
  <IsOpen>false</IsOpen>
</SerialPortState>

Si noti che questo file di configurazione non viene richiesta assistenza per aprire la porta COM automaticamente, in modo da dover inviare una richiesta Open.

Se si desidera che il servizio di avere un aspetto professionale, è necessario prestare attenzione ai dettagli quali la descrizione del servizio e icone. Anche se si Don ’t prevede di utilizzare VPL manualmente, è consigliabile verificare il servizio in VPL e rendere VPL descrittivo in modo che altri utenti possono utilizzare con facilità.

Decorare la classe di servizio con due attributi che descrivono il servizio:

[DisplayName("Serial Port Service")]
[Description("SerialPort service provides access to a Serial (COM) Port")]

Visualizza il primo attributo come nome del servizio nell'elenco del servizio VPL (vedere Nella figura 5) e il secondo attributo viene visualizzato come descrizione se si sposta il mouse sul nome del servizio nell'elenco.


Nella figura 5 Elenco servizi VPL

Se si dispone di un sito Web e si desidera documentare i servizi in linea, è possibile allegare un altro attributo alla classe di servizio per fornire il collegamento ipertestuale:

[DssServiceDescription("http://www.promrds.com/SerialPort.htm")]

Quando VPL rileva questo attributo, aggiunge un'icona informazioni di piccole dimensioni (“ i ” su un disco blu bianco) accanto al servizio nell'elenco del servizio.

Se si aggiungono icone al servizio, è possibile eseguire, verrà appaiono nell'elenco del servizio e VPL diagrammi. Si noti l'icona piccola chiamato una miniatura, accanto al nome del servizio in Nella figura 5Nella figura 6 illustra la versione più grande dell'icona, verrà visualizzato all'interno del blocco che verrà visualizzato nei diagrammi VPL.


Nella figura 6 Blocco del servizio

Quando si aggiungono queste immagini a un progetto, assicurarsi di che modificare le proprietà del file in modo che l'operazione di generazione è impostata su Embedded Resource. PNG è il formato di file preferito, poiché supporta un canale alfa. In questo modo è possibile creare un'icona con uno sfondo trasparente, impostare il valore alfa sul colore di sfondo a zero.

Immagine dell'icona di servizio deve essere 32 x 32 pixel e l'anteprima di 16 x 16. I nomi dei file delle immagini devono iniziare con il nome della classe di servizio, in questo caso SerialPortService. In questo modo ho apportato i nomi di file per il mio esempio SerialPortService.Image.png e SerialPortService.Thumbnail.png.

Uso del servizio

Il servizio è piuttosto flessibile. È possibile specificare la configurazione della porta seriale in un file di configurazione (che è il modo più comune) o inviando una richiesta SetConfig. Dopo aver impostato la configurazione, è possibile chiamare l'operazione di apertura. Per comodità, un flag nel file di configurazione causerà il servizio aprire la porta automaticamente all'avvio. Se la porta è già aperta, la chiamata a Open verrà prima chiudere, quindi riaprirlo.

È necessario decidere come si desidera utilizzare il servizio: in modo sincrono o asincrono. Quando si opera in modalità sincrona, ciascuna lettura o scrittura richiesta attenderà il completamento dell'operazione prima di inviare nuovamente una risposta. In termini di VPL, è un approccio semplice, poiché il flusso dei messaggi verrà sospesa blocco SerialPort nel diagramma. Si noti che l'operazione asincrona non è completamente asincrono, ovvero scrivere comunque eseguite operazioni in modo sincrono. Ma ogni nuovo byte ricevuto viene inviato come una notifica ai sottoscrittori.

In teoria, ogni operazione di modifica dello stato di un servizio dovrebbe causare una notifica da inviare in modo che i server di sottoscrizione può mantenere la propria versione memorizzata nella cache dello stato del servizio. Ciò significa che tutte le operazioni in base alle operazioni DSSP Sostituisci, Update, INSERT, DELETE e Upsert devono inviare una notifica corrispondente. Tuttavia, gli sviluppatori spesso riproduzione rapida e allentati questo requisito.

Per semplicità, il servizio SerialPort solo invia notifiche utilizzando il tipo di operazione ReceiveByte in modalità asincrona. Open, Close, e operazioni SetConfig determinano le notifiche da inviare.

Poiché le operazioni di lettura e scrittura non modificano lo stato, sono una sottoclasse disattiva l'operazione di invio DSSP. Naturalmente, hanno un effetto collaterale, ovvero per ricevere e inviare dati tramite il collegamento seriale.

Test con VPL

Download di questo articolo include due programmi VPL di esempio, EchoAsynch e EchoSynch, viene illustrato come utilizzare il servizio in modalità asincrona (tramite notifiche) e modalità sincrona. Gli esempi VPL utilizzano file di configurazione per impostare i parametri iniziali per la porta COM, incluso il numero della porta (che è impostato su 21 in file config e deve essere modificato per corrispondere l'indirizzo della porta COM del computer in uso).

Si noti che per eseguire il test del servizio è necessario un cavo null modem e due computer con le porte seriali o due porte nello stesso computer. Periferiche USB a seriale sono disponibili, pertanto è abbastanza fattibile dispone di più porte seriali di un unico computer. Quando si dispone di porte COM connesse tra loro, eseguire un emulatore di terminale quali HyperTerminal e connettersi a una delle porte COM. Iniziare eseguendo il programma EchoAsynch VPL sulla porta seriale. (È possibile trovare VPL dal menu di avvio in RDS). Quando si digita nella finestra dell'emulatore di terminale, dovrebbero essere visualizzati i caratteri.

È possibile utilizzare VPL per creare file di configurazione. Fare clic su un blocco di servizio SerialPort nel diagramma e controllare nel Pannello proprietà. Dovrebbe essere visualizzato qualcosa di simile a Nella figura 7. Assicurarsi che il numero di porta sia impostata correttamente per il PC. (Deve trattarsi di porta seriale, non la si aperto nell'emulatore di terminale). Si noterà che parità e StopBits sono elenchi a discesa. Le voci utilizzando gli elenchi di provenire direttamente da enumerazioni definite in SerialPortTypes.cs.


Nella figura 7 Configurazione servizio porta seriale.

Si tratta di un'unica posizione in cui i commenti del documento XML rivelarsi utili. Quando si posiziona il puntatore del mouse su un parametro di configurazione con il cursore del mouse, verrà visualizzata una descrizione comandi contenente il commento corrispondente per ogni membro stato.

Quando si esegue il programma EchoAsynch VPL, la prima parte del programma in Nella figura 8 apre la porta seriale in modalità asincrona.


Nella figura 8 Apertura porta seriale in modalità asincrona

Se si sono immessi valori non validi nel file di configurazione, ad esempio una velocità di trasmissione non valido, Apri avrà esito negativo. (Potrebbe inoltre esito negativo se la porta COM è in uso, la porta non esiste o non si dispone di autorizzazioni appropriate). Questo è il motivo per cui il programma verifica la presenza di un errore e lo visualizza.

Il resto del programma (vedere Nella figura 9) semplicemente l'eco ogni carattere ricevuto. A tale scopo utilizzando i caratteri da ReceiveByte notifiche e inviarli nuovamente utilizzando WriteByte.

Per semplificare la lettura dell'output, un ritorno carattere (ASCII 13, decimal) ha un avanzamento riga (10) aggiunto in modo che il cursore si sposterà alla riga successiva nella finestra emulatore di terminale. Si noti che tutti i SerialPortService in Nella figura 9 diagramma fare riferimento alla stessa istanza del servizio.


Nella figura 9 Programma EchoAsynch

Il programma EchoSynch VPL (vedere Nella figura 10) utilizza la modalità di funzionamento sincrona, ovvero non utilizza le notifiche. (Infatti, le notifiche non vengono mai inviate in modalità sincrona).


Nella figura 10 Il programma EchoSynch

A differenza del programma precedente, questo utilizza ReadString e WriteString dati echo. Queste operazioni eseguono funzioni simili a quelli di ReadByteArray e WriteByteArray, tuttavia, le stringhe sono più facili da gestire in VPL rispetto alle matrici di byte.

Le operazioni di stringa utilizzano un carattere di avanzamento riga (o di nuova riga) come un indicatore di fine della riga. Pertanto, ReadString completa quando si preme avanzamento riga (CTRL-J) non quando si preme INVIO. Ciò può confondere la prima volta il programma utilizzando un emulatore di terminale è test perché ci si potrebbe chiedere perché non è eco. WriteString aggiunge un ritorno a capo e avanzamento riga per l'output in modo che venga visualizzato ogni stringa su una riga separata.

Si noti che il file config per EchoSynch un InterCharacterDelay di 500ms. In questo modo, le stringhe devono essere inviati molto lentamente. È possibile provare a modificare questo valore.

Trevor Taylor* Ph.D., è program manager per Robotics Developer Studio presso Microsoft. È inoltre coautore, con Kyle Johns, di “ Professional Robotics Developer Studio ” (Wrox, 2008). Codice di esempio dal libro è disponibile da promrds.com.*

* *

Grazie ai seguenti esperti tecnici per la revisione di questo articolo:Kyle Johns