Erste Erfahrungen in C probleme mit Variablen?


10 posts
by bismosa » Sat Feb 16, 2013 5:49 pm
Hallo!

Ich mache gerade meine ersten Erfahrungen in C auf dem Raspberry.
Ich lese einen USB-RFID Reader aus, der sich als USB-Laufwerk anmeldet. Ich habe nach langer sucherei zwei sehr tolle Seiten gefunden (Ich bin mir nicht sicher, ob ich den Code aus anderen Foren einfach kopieren darf ?):
http://stackoverflow.com/questions/7668 ... block-them
Dort ist in der ersten Antwort ein Beispiel für das Auslesen der Tastatur im Exklusivzugriff. Ich habe dort mein Device eingetragen und das Script läuft super.
Auf dieser Seite
https://github.com/lahdekorpi/HID-RFID- ... r/daemon.c
ist eigentlich das gleiche. Nur das hier auch die Keycodes gleich übersetzt werden. Ich schaffe es aber nicht das Script zu kompilieren. Ich vermute das die variable nicht richtig initialisiert wird?
Code: Select all
read2.c: In function ‘main’:                                                                                                                                     
read2.c:34:1: error: ‘keycodes’ undeclared (first use in this function)                                                                                           
read2.c:34:1: note: each undeclared identifier is reported only once for each function it appears in                                                             
read2.c:34:12: error: expected expression before ‘{’ token                                                                                                       
read2.c:65:1: error: ‘pid’ undeclared (first use in this function)                                                                                               
read2.c:111:1: error: expected declaration or statement at end of input                                                                                           
read2.c:111:1: error: expected declaration or statement at end of input                                                                                           
make: *** [read2] Error 1   

Also habe ich versucht die Variable zu initialisieren:
Code: Select all
char keycodes[] = {
[0]="UNKNOWN",
...

Dann bekomme ich noch viel mehr Fehlermeldungen:
Code: Select all
read2.c: In function ‘main’:                                                                                                                                     
read2.c:36:1: error: excess elements in char array initializer                                                                                                   
read2.c:36:1: error: (near initialization for ‘keycodes’)                                                                                                         
read2.c:36:1: error: excess elements in char array initializer                                                                                                   
read2.c:36:1: error: (near initialization for ‘keycodes’)                                                                                                         
read2.c:36:1: error: excess elements in char array initializer     
....   


Was mache ich falsch? Wäre super, wenn mir jemand kurze Starthilfe geben könnte..ich vermute es ist so einfach...das ich mit meinen Suchbegriffen bei Google nichts finden kann...

Danke

Gruß
Bismosa
Posts: 16
Joined: Sun Dec 23, 2012 11:43 am
by Hiswif » Sat Feb 16, 2013 6:15 pm
Huhu.

Was mache ich falsch?


Gleich mit nem RFID-Reader am USB anzufangen und sich den Code von anderen zu nehmen würde ich schon als ersten Fehler ansehen. Nicht das wir uns falsch verstehen, diese Scripte zu nutzen ist nichts schlechtes, nur sollte man am Anfang nicht mit etwas copierten Anfangen, sondern erstmal versuchen die Grundlagen zu verstehen. Sich in fremden Code einzuarbeiten und diesen zu verstehen ist selbst für professionelle Programmierer eine Aufgabe, die diese meist ungern übernehmen und die jede Menge Grundwissen voraussetzt. Wenn du dann noch, wie in deinem Fall, auf einen Fehler stößt wird es ganz kriminell. Die Frage ist nun wie man das ganze erklären soll wenn du gerade erst am Anfang deiner Kenntnisse stehst aber eine Erklärung für Fortgeschrittene brauchst.
Bitte versteh mich nicht falsch. Das soll kein Angriff gegen dich sein oder dich in irgendeiner Weiße schlechtmachen. Ich finde nur das man alles am Anfang beginnen sollte und nicht in der Mitte oder zum Schluss. So einen Code zu lesen und den Fehler zu finden erfordert nunmal Grundlagen.

Ich tippe ja eher auf einen linkerfehler. Aber habe grad auch keine Zeit mir das ganze mal anzuschauen. Da der code ja auch nicht wirklich dokumentiert ist. Wird wahrscheinlich erst mitte der Woche.

Kannst du mal deinen Compilierbefehl posten?

Solltest du wirklich noch am Anfang stehen mit dem Programmieren empfehle ich dir

http://openbook.galileocomputing.de/c_von_a_bis_z/

und

http://de.wikibooks.org/wiki/C-Programmierung

Diese sind kostenlos verfügbar und sollten dir für den Anfang absolut ausreichen.

MFG

His
http://technikegge.blogspot.de
User avatar
Posts: 506
Joined: Sat Oct 13, 2012 11:54 am
by naicheben » Sat Feb 16, 2013 7:09 pm
In der von Dir verlinkten deamon.c steht das doch so drin:
Code: Select all
keycodes = {
[0]="UNKNOWN",


Warum hast Du denn die [] hinter keycodes geschrieben?
Posts: 346
Joined: Sat Jan 28, 2012 12:28 pm
by bismosa » Sat Feb 16, 2013 7:27 pm
Hallo!
@Hiswif
Danke für die Buchtips! Die sind wirklich nicht schlecht.
Ich stehe ja nicht am Anfang der Programmiererei...sondern am Anfang meiner C Kentnisse. Bisher habe ich einige Projekte in VB.net und Java umgesetzt. (Hauptsächlich für PC Anwendungen). Auch wenn ich da kein Profi bin...als fortgeschritten würde ich mich da schon bezeichnen. Auch Html und Php sind für mich keine Fremdworte mehr. Bisher habe ich nie Kurse für so etwas besucht. Das meiste sind auch Hobbyanwendungen...auch wenn ich enige Projekte auch produktiv in der Firma benutze.
Meine Raspberrys habe ich jetzt schon eine ganze Zeit. Daher habe ich mich auch schon gut mit der Bash Programmierung und Linux auseinandergesetzt. Python und C stehen jetzt quasi als nächstes auf meiner Liste.
Mein RFID Reader läuft schon (fast) problemlos mit einem Bash-Script. Ich steuere über CLI meine Squeezebox inkl. meine Stereoanlage...die vom Raspberry mit Hilfe einer Relaisplatine und Lirc gesteuert wird.
Leider kommt es bei meinem Bash-Script immer wieder vor, dass ich die Karten 2x einlesen muss, bis ich die Nummer verarbeiten kann. Das liegt m.E. daran, dass ich mit der Zeile
Code: Select all
read -p "Warte auf RFID Code.... " code </dev/tty1

keinen Exklusivzugriff habe und eigentlich mit der emulierten Tastatur in die Shell schreibe.
Vielleicht liege ich ja falsch...aber ich habe mit dem Exklusivzugriff (aus dem ersten Beispiel) immer eine Rückmeldung. Ich habe lange (ich mag die Stunden gar nicht mehr zählen...ich bin seit 2 Wochen dabei) gegoogelt um eine Lösung für mein Problem zu finden...um so glücklicher bin ich, das ich mit dem Weg vermutlich nicht ganz in die falsche Richtung gehe.
Ich habe die Besten Erfahrungen für mich gemacht, wenn ich (gerade am Anfang) auf bestehende Beispiele aufsetze. Da lerne ich aus dem Besipiel und aus dem, was ich dann noch dazu schreibe...denn das auslesen des Codes ist ja nur der Anfang.
Tja...vielleicht muss ich mich wirklich erst einmal mit den Compiler näher beschäftigen...denn Compilerbefehl sagt mir so nichts. Ich nutze immer einfach nur "make ...".

@naicheben
Ich kenne es von anderen Programmiersprachen, dass so arrays deklariert werden. Google hatte mich auch darauf gebracht...ich habe aber gerade (im Openbook) gelesen, dass es keine wachsenden Arrays in C gibt. Also hätte es doch eigentlich
Code: Select all
char keycodes[265] = {

sein müssen?

Ich denke halt, das der (mein) Fehler in dieser Variablen versteckt ist...

Danke für die Hilfen!

Gruß
Bismosa
Posts: 16
Joined: Sun Dec 23, 2012 11:43 am
by Hiswif » Sat Feb 16, 2013 9:59 pm
Huhu.

ok, dann hatte ich deinen Satz

Ich mache gerade meine ersten Erfahrungen in C auf dem Raspberry.


einfach nur falsch verstanden. Gab ja zwei möglichkeiten den zu deuten ;)

Ok dann fangen wir mal an.

1. Was soll dein RFID reader können? Also was ist das Ziel was du mit ihm tun willst?
2. wenn du "make" benutzt. Kannst du mal bitte das makefile posten?

Ich glaube halt einfach das du die erfolrderlichen libs einfach nicht verlinkt hast und deshalb Fehlermeldungen bekommst. Mein Pi ist nur gerade in der konfiguratiopn das ich das selber nicht nachprüfen kann, da ich dann erst mein Projekt komplett sichern, standard wiederherstellen .... müsste. Zweite SD ist grad mit XBMC belegt ;) Deshalb muss ich grad mal versuchen das aus der kalten zu machen ;)

In der Einleitung der deamon.c steht

Code: Select all
Code based on an example code by https://github.com/gpisacco


Hast du dir das Orginal mal angeschaut? Eventuell liegt in der Beschreibung des Orginals ja nen hinweis?

Wie gesagt ;) INFOS INFOS INFOS ;)

MFG

His
http://technikegge.blogspot.de
User avatar
Posts: 506
Joined: Sat Oct 13, 2012 11:54 am
by bismosa » Sun Feb 17, 2013 5:03 pm
Hallo!

Dann will ich mal etwas weiter ausholen.
Also zunächst mein Vorhaben:
Ich besitze eine Squeezebox Touch und ein Squeezebox Radio. Dazu habe ich noch einige Softwareplayer auf dem Rechner + IPhone...also ein Logitech Musik System, das mit einem lokalen Server (das lasse ich auf meinem RPi laufen) arbeitet. Steuern lässt sich das System sehr praktisch über ein CLi interface.
Nun ist es so, das meine 3 Jahre alten Zwillinge nicht so richtig gut mit CD´s (trotz des Servers haben wir auch CD´s) umgehen können. Ständig darf man neue Sicherungen davon erstellen, da die alten zerkratzt sind. Zudem habe ich mal ein Projekt gesehen, wo jemand mit einem Mikrocontroller einen RFID-Reader steuert und damit dann seine Musikbibliothek. Das will ich auch...allerdings mit Hilfe des Raspberrys.
Also habe ich mir bei ebäh einen ganz billigen RFID-Reader besorgt, der sich als Tastatur über USB anmeldet. Und habe meine Versuche gestartet. Mein Bash-Script läuft auch wie bereits geschrieben fast vollständig.
Code: Select all
#!/bin/bash
#
#Variablen laden aus Datei...
# Absolute path to this script, e.g. /home/user/bin/foo.sh
SCRIPT=$(readlink -f $0)
# Absolute path this script is in, thus /home/user/bin
SCRIPTPATH=$(dirname $SCRIPT)
echo $SCRIPTPATH

source $SCRIPTPATH/settings.sh

#Logging bei bedarf einschalten
if test -t 1; then
   #local gestartet...nichts unternehmen
   if [ $Debug -eq 1 ]; then
      echo "Werde keine Log-Datei schreiben..."
      #   exec 2>&1 | tee $SCRIPTPATH/rfid.log
   fi
else
   #als Dienst gestartet...loggen wenn gewünscht
   if [ $Debug -eq 1 ]; then
      exec >$SCRIPTPATH/rfid.log 2>&1
   fi
fi

#Startvariablen
Endzeit=0

while [ true ]
do
   
   sonderfunktion=0
   
   read -p "Warte auf RFID Code.... " code <$EingabeGeraet
   echo "Folgender Code wurde eingelesen: $code"
   
   #Testen, ob es sich um einen RFID-Code handelt
   if ! [[ "$code" =~ ^[0-9]+$ ]] ; then
      echo "$code ist kein RFID TAG!!!"
      continue
   fi

#Testen, ob es eine Sonderfunktion ist
   testvar=$(echo $(eval echo \${VR$code}))
   #testvar=$(echo $((VR$code)))
   echo "-$testvar-"
   if [ ${#testvar} = 0 ]; then
      echo "Keine Sonderfunktion"
   else
      #Sonderfunktion
      echo "-$testvar-"
      sonderfunktion=1
   fi
   
         
#Ein zu schnelles Einlesen verhindern
   Startzeit=$(date +%s)
   echo $Startzeit
if [ $sonderfunktion -ne 1 ]; then    #Lauter etc. nicht ausbremsen
   if [ $Endzeit -ne 0 ]; then
      if [ $code -eq $codealt ]; then
         #Es ist der gleiche Code....erst nach xx Sekunden
         if [ $(($Startzeit - $Endzeit)) -lt 10 ]; then
            echo "Gleicher RFID-Code...nicht so schnell!!!"
            continue
         fi
      else
         #Es ist ein anderer code....erst nach xx Sekunden
         if [ $(($Startzeit - $Endzeit)) -lt 3 ]; then
            echo "Nicht so schnell!!!"
            continue
         fi
      fi
   fi
fi

   if [ $sonderfunktion -eq 1 ]; then
      echo "Führe funktion $testvar aus..."
      (echo "$testvar"; sleep 0.1) | nc $ServerIP $ServerPort
      echo "$PlayerMAC display Führe%20folgende%20Funktion%20aus: ${testvar// /%20}" | nc -i 1 $ServerIP $ServerPort
      continue
   fi
   
   #Nur zum testen
   #playercount=`(echo "player count ?"; sleep 0.1) | nc $ServerIP $ServerPort`
   #echo $playercount
   
   playlistcount=`(echo "playlists 0 1 search:$code"; sleep 0.3) | nc $ServerIP $ServerPort`
   
   echo $playlistcount
   if [ "${playlistcount:(-1)}" == "1" ]; then
      echo "Playlist gefunden!"
      (echo "$PlayerMAC playlist play $code"; sleep 0.1) | nc $ServerIP $ServerPort
      echo "$PlayerMAC display Starte%20Playlist $code" | nc -i 1 192.168.183.21 9090
   else
      echo "nicht gefunden!!"
      echo "$PlayerMAC display Der%20Code%20$code wurde%20nicht%20gefunden!!" | nc -i 1 $ServerIP $ServerPort
   fi
   
   #Um ein zu schnelles Einlesen zu verhindern
   Endzeit=$(date +%s)
   codealt=$code
done

read -n 1
echo "fertig"


und dazu die settings:
Code: Select all
#Einstellungsdatei für rfid.sh
#
# Hier werden alle Einstellungen und Sonderfunktionen konfiguriert
#
#Einstellungen
#Debug -> Wenn 1 dann wird im Startverzeichnis eine Log-Datei geschrieben (rfid.log)
Debug=0
#ServerIP -> IP-Adresse vom Squeezebox Server
ServerIP="192.168.183.21"
#ServerPort -> Standard 9090
ServerPort="9090"
#Eingabegerät -> Das Gerät, was die zeichen vom RFID-Reader zurückgibt
EingabeGeraet="/dev/tty1"
#PlayerMAC -> Die MAC des Players, der gesteuert werden soll
PlayerMAC="00:04:20:22:91:6d"

#Sonderfunktionen hier hinterlegen:
#Es muss immer ein VR der Kartennummer vorangestellt werden!!
#Es können alle CLI Kommandos ausgeführt werden
#
VR0003244512="$PlayerMAC display Sonderfunktion..."
VR0003231703="$PlayerMAC power 0"
VR0003670208="$PlayerMAC pause"
VR0003704451="$PlayerMAC mixer volume +5"
VR0003680339="$PlayerMAC mixer volume -5"
VR0003244512="$PlayerMAC mixer muting"
VR0003693318="$PlayerMAC playlist index +1"
VR0003701069="$PlayerMAC playlist index -1"


Nun ist es so, das ich direkt aus tty1 lese...aber nicht im Exclusivzugriff. Daher bekomme ich nicht immer die Ausgabe...und ich bin auf der Suche nach einer Lösung.
Sicherlich ist mein erster Fehler gewesen, ein USB-Reader zu kaufen. Ein serieller wäre vermutlich einfacher für mich...
Zu der Funktion:
Es wird auf ein RFID-TAG gewartet. Dieser wird auf gültigkeit Überprüft. Danach werden die hinterlegten RFID-Tags abgefragt, ob eine "Sonderfunktion" wie z.B. lauter, leiser etc. damit gewünscht ist. Ist das nicht der Fall, wird einfach die Playlist mit der eingelesenen Nummer gestartet.
So können ganz einfach weitere Alben mit RFID-Tags ausgestattet werden. Einfach eine Playlist mit der NUmmer anlegen und Karte einlesen...das wars.

Ich habe jetzt aufgrund der Bemerkungen von Dir etwas weiter geforscht. Bei dem verwiesenen Projekt ist nichts drin. Allerdings habe ich diese Seite gefunden:
https://gist.github.com/gpisacco/3161554/download#
dort ist das gesuchte...auch ein Makefile. Der Code lässt sich problemlos kompilieren. Aber bei der näheren Betrachtung habe ich festgestellt, das es nicht so einfach ist, wie ich es eigentlich erhofft hatte. C ist doch wohl um einiges schwieriger als ich dachte. Von dem Code verstehe ich nicht sehr viel...zumindest zu wenig um damit weiter zu machen und das Projekt damit umzusetzen(?)
Bisher hatte ich so gut wie keine Berührung mit C. Wenn dann waren es alles Projekte, die kein Makefile hatten...daher bin ich auch nicht darauf gekommen. Aber mit dem was in dem Makefile steht, kann ich so gut wie gar nichts anfangen.
Ich vermutete eigntlich, das es in C einfacher sein würde mein Vorhaben umzusetzen. Gerade wenn ich noch ein paar Sonderfunktionen hinzuprogrammieren möchte...wie z.B. eine Lautstärkeveränderung bis zu einer vorgegebenen Lautstärke...und was mir nicht noch alles einfallen würde...aber zunächst müsste ich die Sachen aus dem Bash-Script in C übertragen.

Daher suche ich weiter eine (einfache) Möglichkeit die Eingaben der RFID-Tastatur einzulesen. Ich habe jetzt noch diesen Beitrag gefunden:
http://www.linuxquestions.org/questions ... post372925
vielleicht geht das eher in die richtige Richtung? Obwohl es mit C ja gut funktionieren würde...oder sollte ich es lieber so machen, das ich mit meinem Bash-Script das C-Programm aufrufe und die Rückgabe (also die RFID-Nummer) verarbeite? Ich denke das wäre ein eher unüblicher weg?

Vielleicht stehe ich ja nur gerade auf dem Schlauch...und denke viel zu kompliziert...

Danke für die Bemühungen!

Gruß
Bismosa
Posts: 16
Joined: Sun Dec 23, 2012 11:43 am
by diru » Sun Feb 17, 2013 6:04 pm
Hey deine Array-Dekleration ist schon richtig, jedoch sind Strings selbst auch Arrays (Null-terminierte Arrays aus chars, wenn ich mich nicht irre;-). D.h. entweder machst du ein Array aus char-Pointern oder ein Array of Arrays aus chars:

Code: Select all
char* keycodes[] = {
 "ABC", "BCD", ...
}


Meines Wissens nach ist das bei Java nicht groß anders mit Ausnahme der Codierung. In C steht dir ANSI zur Verfügung, Java codiert Strings beim kompilieren als UTF-16.

VG, Dirk
Posts: 9
Joined: Fri Jan 11, 2013 3:06 pm
by Hiswif » Sun Feb 17, 2013 9:00 pm
Ganz ehrlich. Das ganze interessiert mich inzwischen brennend. Habe selber einen 2 jährigen Sohn und was du da anstrebst klingt echt gut. Vorallem weil ich dann nen Grund habe einen zweiten Pi vor meiner Frau zu rechtfertigen ;)
Ich hab da auch in der letzten Woche was zu gelesen. Da ging es auch um solch einen günstigen rfid Leser. Ich muss morgen mal schauen.
http://technikegge.blogspot.de
User avatar
Posts: 506
Joined: Sat Oct 13, 2012 11:54 am
by bismosa » Sun Feb 17, 2013 9:33 pm
Hallo!
Ich habe es wirklich einfach gehalten und mir den billigsten aus China geholt (10€). Da das erste Paket Monate gebraucht hat...hat der Verkäufer den nochmal losgeschickt. Es lohnt sich wenn man es eilig hat die Lieferung per Luftpost zu nehmen. Jetzt habe ich schon zwei...aber auch zwei unterschiedliche. Aber beide melden sich normal als Tastatur an.
http://thetransistor.com/2011/10/hackin ... d-readers/
Das hatte mich auf die gebracht...ich wollte eigentlich auch gerade die serielle schnittstelle haben (für das Squeezebox Radio...dort gibt es ein seriellen Anschluss) aber ich habe zwei andere Versionen. Dort konnte ich kein serielles Signal finden...(allerdings habe ich auch keinen Logigtester).

Im Wohnzimmer habe ich meinen Raspberry...weshalb er gut die Aufgabe mit RFID übernehmen kann. Im Kinderzimmer habe ich vor ein Squeezebox Radio hinzustellen. Aber ohne Raspberry. Dafür ist mir der Strom schon zu teuer...aber bis zu der Lösung wird es wohl noch dauern.
Übrigens stellt Logitech die Squeezebox Reihe gerade um...das nennt sich jetzt UE und ist komplett Online-basierend. Aber ich will nicht meine Musik auf deren Server laden um lokal etwas zu hören...da bin ich noch nicht richtig begeistert von...

Meine Kinder spielen jetzt schon sehr gerne damit rum! Sind auch gleich damit klar gekommen. Mal schauen, ob ich das meiner Frau auch noch beibringen kann ;)

Gruß
Bismosa
Posts: 16
Joined: Sun Dec 23, 2012 11:43 am
by Hiswif » Mon Feb 18, 2013 7:43 am
Huhu.

Schau mal hier. Vieleicht hilft dir das ja weiter.

http://hackaday.com/2013/02/16/turning- ... ng-useful/

Orginal ist aber in französisch. Google translate sollte aber helfen. Spreche leider nur englisch und russisch.

Mfg

His
http://technikegge.blogspot.de
User avatar
Posts: 506
Joined: Sat Oct 13, 2012 11:54 am