2008-10-02 3 views
6

Ich schreibe ein DSL in Ruby, um ein Arduino-Projekt zu steuern, an dem ich arbeite; Bardino. Es ist ein Baraffe, der softwaregesteuert wird, um Getränke zu servieren. Der Arduino nimmt über den seriellen Port Befehle entgegen, um dem Arduino zu sagen, welche Pumpen eingeschaltet werden sollen und für wie lange.Brauchen Sie Hilfe ein Ruby DSL für die Steuerung eines Arduino kontrollierten Getränkespender zu verbessern (Bar Affe)

Es liest derzeit ein Rezept (siehe unten) und druckt es wieder aus. Der Code für die serielle Kommunikation muss noch bearbeitet werden, ebenso wie einige andere Ideen, die ich unten erwähnt habe.

Dies ist meine erste DSL und ich arbeite von einem vorherigen Beispiel, so dass es sehr rau an den Rändern ist. Irgendwelche Kritik, Code-Verbesserungen (gibt es irgendwelche guten Referenzen für Ruby DSL Best Practices oder Idiome?) Oder allgemeine Kommentare.

Im Moment habe ich einen groben Entwurf des DSL so ein Getränk Rezept sieht wie folgt aus (Github link):

desc "Simple glass of water" 
recipe "water" do 
    ingredients(
    "Water" => 2.ounces 
) 
end 

Dies wiederum interpretiert und führt derzeit mit der folgenden (Github link):

[[email protected] barduino-tender]$ ruby barduino-tender.rb examples/water.rb 
Preparing: Simple glass of water 

Ingredients: 
Water: 2 ounces 

Dies ist ein guter Start für die DSL, aber ich denke, es könnte ein bisschen besser umgesetzt werden. Einige Ideen, die ich unten hatte:

  1. Definieren, was "Zutaten" sind mit dem Namen der Zutat und der Nummer Pumpe, die es verbunden ist. Vielleicht mit einem Hash? Zutaten = {"Wasser" => 1, "Wodka" => 2}. Wenn eine Zutat interpretiert wird, kann sie entweder a) die Pumpennummer über die serielle Schnittstelle senden, gefolgt von der Anzahl der Unzen, die der Arduino ausgeben soll. B) dem Benutzer mitteilen, dass keine Zutat vorhanden ist, und abbrechen, so dass nichts ausgegeben wird. leicht die Fähigkeit haben, neue Zutaten zu ändern oder hinzuzufügen, wenn sie geändert werden.
  2. Machen Sie das Rezept aussehen weniger Code wie, was ist der Hauptzweck eines DSL, vielleicht ein Rezept Builder bauen? Verwenden Sie die verfügbaren Zutaten, um den Benutzer auf einen Namen, Zutaten beteiligt und wie viel?

Das Github-Projekt ist here, fühlen sich hier frei gabeln und Pull-Anforderungen zu machen, oder posten Sie Ihre Code Anregungen und Beispiele für andere Benutzer zu sehen. Und wenn Sie überhaupt neugierig sind, ist der Arduino-Code mit dem Ruby Arduino Development Framework here.

aktualisieren

I modifiziert und gereinigt Dinge ein wenig bis zum Orion Edwards Vorschlag für ein Rezept zu reflektieren. Es sieht jetzt wie folgt aus.

description 'Screwdriver' do 
    serve_in 'Highball Glass' 
    ingredients do 
    2.ounces :vodka 
    5.ounces :orange_juice 
    end 
end 

Ich habe auch einen Hash hinzugefügt (Schlüssel ist die Zutat und der Wert die Pumpennummer, die es angeschlossen ist). Ich denke, das hat viel Fortschritt gebracht. Ich werde die Frage zunächst für weitere Vorschläge offen lassen, werde aber letztendlich Orions Antwort wählen. Der aktualisierte DSL-Code lautet 10.

+0

Um etwas Pseudo-Code zu der Mischung hinzuzufügen. für Zutat in Zutaten {wenn Zutat.existiert? serial.send (pump_number) warte 1 Sekunde serial.send (Menge) warte auf OK von Arduino um mit der nächsten Zutat fortzufahren} – mwilliams

Antwort

5

Ohne Implementierungsdetails der Suche in (oder Ihre Github Links), würde ich versuchen, einen DSL so schreiben:

(Stehlen von hier: http://supercocktails.com/1310/Long-Island-Iced-Tea-)

describe "Long Island Iced Tea" do 
    serve_in 'Highball Glass' 

    ingredients do 
    half.ounce.of :vodka 
    half.ounce.of :tequila 
    half.ounce.of :light_rum 
    half.ounce.of :gin 
    1.dash.of :coca_cola 
    #ignoring lemon peel as how can a robot peel a lemon? 
    end 

    steps do 
    add :vodka, :tequila, :light_rum, :gin 
    stir :gently 
    add :coca_cola 
    end 
end 

Hoffnung, das hilft!

+0

du könntest 0,5.ounces.of: wodka wenn du dich so fühlst, finde ich einfach den alias für ' halb 'besser lesbar sein –

+0

Danke für diesen Tipp, das ist eigentlich _a viel_ lesbarer und ich werde mich entsprechend in der nächsten Revision anpassen. – mwilliams

1

Orions DSL sieht sehr nett aus. Die einzige Änderung, die ich möglicherweise von Ihnen „aktualisiert“ Code würde vorschlagen, ist

  1. ersetzen description mit recipe. Es ist ein beschreibender Begriff
  2. Da die Menge der Zutaten und Aktionen festgelegt ist, binden Sie die Zutaten an Variablen anstelle von Symbolen, d. H. Sie haben vodka = :vodka irgendwo definiert. Es ist einfacher zu sagen

    mischen Sie Wodka, Gin und triple_seC# anstelle von: Wodka,: Gin und: triple_sec.

sowieso ist das eine kleine nit.

+1

Ich persönlich stimme nicht mit verbindlichen Zutaten zu Variablen, denn gut, Variablen sind so konzipiert, variieren. Die Bindung an eine Variable "impliziert" den Entwickler implizit. "Wodka" sollte niemals wieder gebunden werden, um tatsächlich "Käse" zu sein. –

+0

stimme dem Ersetzen von "describe" durch "recipe_for" oder Ähnliches zu –

3

Wenn Sie das Rezept natürlicher aussehen soll, warum nicht (aus dem gleichen Rezept Orion Ewards verwendet, danke!):

Recipe for Long Island Iced Tea #1 
Ingredients: 
    1/2 oz Vodka 
    1/2 oz Tequila 
    1/2 oz Light Rum 
    1/2 oz Gin 
    1 Dash Coca-Cola 
    # ignored Twist of Lemon Peel (or Lime) 

Dann Treetop in den Mix. Sie könnten Regeln wie zum Beispiel haben:

grammar Cocktail 
    rule cocktail 
    title ingredients 
    end 

    rule title 
    'Recipe for' S text:(.*) EOF 
    end 

    rule ingredients 
    ingredient+ 
    end 

    rule ingredient 
    qty S liquid 
    end 
# ... 
end 

Welche der Treetop-Compiler in ein schönes Ruby-Modul verwandeln wird. Dann:

parser = CocktailParser.new 
r = parser.parse(recipe)