Script GPIO auslesen und Zustand in ein XML-File schreiben

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
struband
Beiträge: 7
Registriert: 26.03.2015 19:44:42

Script GPIO auslesen und Zustand in ein XML-File schreiben

Beitrag von struband » 26.03.2015 20:22:21

Hallo zusammen

Ich habe von Scripting (noch) nicht wirklich Ahnung und möchte jetzt aber folgende Aufgabe lösen:

Und zwar möchte ich auf meinem Lanner LEC-2310 Industrie-PC mit GPIOs, den aktuellen Zustand der digitalen Eingänge zyklisch abrufen und ihn dann anschliessend in eine XML-Datei schreiben. Den einzigen Weg den ich bis jetzt herausgefunden habe um an die DIs zu kommen, ist über ein Testprogramm des Herstellers. Startet man dieses, erhält man folgenden Output:

Code: Alles auswählen

root@pz-og38-rbb1:/usr/src/dio/bin# ./dio_tst
=== Lanner platform miscellaneous utility ===
LEB-3010 Digital IO V1.0 2011-03-24

Set All Ouput pin to High ...
  ==>Readback All Input pin, value = 0x0f
Set All Ouput pin to Low ...
  ==>Readback All Input pin, value = 0x0f
Set Ouput pin to 1010 ...
  ==>Readback All Input pin, value = 0x0f
Set Ouput pin to 0101 ...
  ==>Readback All Input pin, value = 0x0f
Test completed


Es wird jeweils nur ein DI gleichzeitig aktiv sein. Daraus ergeben sich folgende möglichen Zustände:

Kein DI gesetzt: 0x0f
DI1: 0x0e
DI2: 0x0d
DI3: 0x0b

Mittels folgender Befehlskette ist es mir gelungen den Wert zu isolieren:

Code: Alles auswählen

root@pz-og38-rbb1:/usr/src/dio/bin# ./dio_tst | grep value | tail -n 1 | grep -o '.$'
f
Dieser Wert soll nun in eine Zahl umgeschrieben werden:
f = 0
e = 1
d = 2
b = 3
Und anschliessend in einer XML-Datei gespeichert werden. Hier hören meine Fähigkeiten ziemlich genau auf :( Wie stelle ich dies am besten an?

Vielen Dank schon mal. :)
Zuletzt geändert von struband am 27.03.2015 07:37:37, insgesamt 2-mal geändert.

eggy
Beiträge: 3331
Registriert: 10.05.2008 11:23:50

Re: Script GPIO auslesen und Zustand in ein XML-File schreib

Beitrag von eggy » 27.03.2015 01:55:51

Quick und dirty: Das Folgende ist nur als Lösungsansatz gedacht: es gibt bessere Lösungen und es findet hier keinerlei Fehlerbehandlung statt.

Schreib dir ein XML-Skelett und markiere den Bereich wo die neuen Einträge hinsollen:
log.xml:

Code: Alles auswählen

<xml>
<krams>
<datensatz>
<datensatz>
<!--FOOTER-->
</krams>
</xml>
Nimm awk und gehe damit Zeile für Zeile durch: wenn es die Markierung findet, schreibt es einen neuen Datensatz, sonst gibt es die alte Zeile aus. Falls es an irgendeiner Stelle im log FOOTER findet, malt es davor die neue Zeile rein. Inhalt der neuen Zeile wird durch die Variable krams bestimmt: "head -n1 /tmp/datei" ersetzt Du durch das, was Du bereits hast.

Code: Alles auswählen

awk -f script.awk -v krams=$(head -n1 /tmp/datei)  -i inplace  log.xml 
-i inplace gibts nicht bei jedem awk, falls Deins das nicht kann: die awk Ausgabe in ne neue Datei schreiben und mv

script.awk:

Code: Alles auswählen

BEGIN{
        if (krams=="f") NEU = "da stand f - es soll 0 hin"
        else if (krams=="e") NEU = "da stand e - es soll 1 hin"
        else if (krams=="d") NEU = "da stand d - es soll 2 hin"
        else if (krams=="3") NEU = "da stand 3 - es soll 3 hin"
        else exit(-1)
}
/FOOTER/{print "<datensatz>"NEU"</datensatz>"}
{print $0}
Ordentlich:
Gibts zu Deinem Testprg den Quellcode unter ner brauchbaren Lizenz? Dann wärs evtl besser das Loggen darein zu basteln.

struband
Beiträge: 7
Registriert: 26.03.2015 19:44:42

Re: Script GPIO auslesen und Zustand in ein XML-File schreib

Beitrag von struband » 27.03.2015 07:37:10

Vielen Dank schon mal! :THX:
eggy hat geschrieben:

Code: Alles auswählen

awk -f script.awk -v krams=$(head -n1 /tmp/datei)  -i inplace  log.xml 
Und das rufe ich dann anschliessend per Cron zyklisch auf?

eggy
Beiträge: 3331
Registriert: 10.05.2008 11:23:50

Re: Script GPIO auslesen und Zustand in ein XML-File schreib

Beitrag von eggy » 27.03.2015 08:38:47

Wie gesagt, das Ganze ist nicht sehr schön, denn awk läuft Dir bei jedem Aufruf durch die ganze Logdatei, schreibt es neu.
Und awk ist nicht der schnellste. Bei nem langen Log kann es sein, dass er oben schon wieder anfangen will, wenn er unten noch garnicht fertig ist. Und da gibts noch diverse andere Fallstricke.
Also wenn Du viel loggen willst, würde ich eher die reinen Werte an nen Logfile anhängen ("echo $(deinzeug) >> logdaten") und nur immer dann, wenn Du das xml ansehen willst, es aus der Wertereihe erstellen.

script2.awk (nur zwei der Fälle, den fehlen Rest kriegst Du selbst hin)

Code: Alles auswählen

BEGIN {print "<xml>"}
/f/ {print "<datensatz>0</datensatz>"}
/d/ {print "<datensatz>2</datensatz>"}
END{print "</xml>"}

Code: Alles auswählen

awk -f script2.awk logdaten > ausgabe.xml
Die Datei mit den Logdaten sähe dafür dann so aus

Code: Alles auswählen

f
d
d
f
oder mit passenden mit Zeitstempeln als "f : 2015-03-27" (dann wird die Auswertung mit der 3 aber schwieriger. Da müsste man dann die einzelnen Felder getrennt betrachten. Irgendnen Zeichen (Semikolon) als FS (Feldseperator) nehmen, und den Abgleich nicht auf die ganze Zeile sondern auf $1 machen), sag falls Du dafür auch noch nen Beispiel haben willst.

struband
Beiträge: 7
Registriert: 26.03.2015 19:44:42

Re: Script GPIO auslesen und Zustand in ein XML-File schreib

Beitrag von struband » 27.03.2015 08:44:06

Vielen Dank! Ich denke damit kann ich arbeiten.

So zur Info: Die XML-Datei wird per Webserver zur Verfügung gestellt und von da von diversen Geräten abgeholt.

rendegast
Beiträge: 15041
Registriert: 27.02.2006 16:50:33
Lizenz eigener Beiträge: MIT Lizenz

Re: Script GPIO auslesen und Zustand in ein XML-File schreib

Beitrag von rendegast » 27.03.2015 09:22:31

Kein DI gesetzt: 0x0f
DI1: 0x0e
DI2: 0x0d
DI3: 0x0b

Mittels folgender Befehlskette ist es mir gelungen den Wert zu isolieren:
root@pz-og38-rbb1:/usr/src/dio/bin# ./dio_tst | grep value | tail -n 1 | grep -o '.$'

Dieser Wert soll nun in eine Zahl umgeschrieben werden:
f = 0
e = 1
d = 2
b = 3

Code: Alles auswählen

$ echo $((0x0f))
15
$ echo $((0x0e))
14
$ echo $((0x0d))
13
$ echo $((0x0b))
11
oder auch

Code: Alles auswählen

$ echo "obase=2;$((0x0f))" | bc
1111
$ echo "obase=2;$((0x0e))" | bc
1110
$ echo "obase=2;$((0x0d))" | bc
1101
$ echo "obase=2;$((0x0b))" | bc
1011

# ./dio_tst | grep value | tail -n 1 | grep -o '.$'
würde ich

Code: Alles auswählen

# ./dio_tst | awk '/value/ {print $NF}' | tail -n 1
Die Geschwinidigkeit beider Befehle bei einem 500MB-Testfile ist gleich.
mfg rendegast
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")

artemis
Beiträge: 447
Registriert: 21.12.2005 23:11:11

Re: Script GPIO auslesen und Zustand in ein XML-File schreib

Beitrag von artemis » 27.03.2015 10:04:30

Hallo.
/usr/src/dio/bin
lässt darauf schließen, dass du den Code vom Testprogramm vorliegen hast. Wäre es da nicht einfacher, die Ausgabe abzuändern und einfach nur noch einen XML Header und Footer dran zu bauen?

Bis dann,
artemis

struband
Beiträge: 7
Registriert: 26.03.2015 19:44:42

Re: Script GPIO auslesen und Zustand in ein XML-File schreib

Beitrag von struband » 27.03.2015 11:17:43

artemis hat geschrieben:Hallo.
/usr/src/dio/bin
lässt darauf schließen, dass du den Code vom Testprogramm vorliegen hast. Wäre es da nicht einfacher, die Ausgabe abzuändern und einfach nur noch einen XML Header und Footer dran zu bauen?

Bis dann,
artemis
Nein dieses Programm war leider schon kompiliert. Das Ganze liegt nur noch dort weil ich das Kernelmodul für die GPIOs kompilieren musste.

@all: Vielen Dank schon mal. Ich versuche übers Wochende mithilfe eurer Inputs die Sache zum laufen zu bringen. :THX:

struband
Beiträge: 7
Registriert: 26.03.2015 19:44:42

Re: Script GPIO auslesen und Zustand in ein XML-File schreib

Beitrag von struband » 15.04.2015 17:54:47

Hallo! Ich wieder einmal ;)

Evtl. geht der Zugriff auch ohne das Testprogramm. Ich bin nämlich noch auf ein File gestossen mit diesem Inhalt:

Code: Alles auswählen

#include "../include/config.h"


#ifdef DJGPP

/* standard include file */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/* For DOS DJGPP */
#include <dos.h>
#include <inlines/pc.h>

#else //DJGPP
/* For Linux */


#ifdef DIRECT_IO_ACCESS
/* For Linux direct io access code */
/* standard include file */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#if defined(LINUX_ENV)
#include <sys/io.h>
#endif

#if defined(FreeBSD_ENV)
#include <machine/cpufunc.h>
#endif


#include <time.h>
#include <stdint.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#define delay(x) usleep(x)
#endif


#ifdef MODULE

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <linux/delay.h>

#undef delay
#define delay(x) mdelay(x)
#undef fprintf
#define fprintf(S, A)  printk(A)

#endif //MODULE


#ifdef KLD_MODULE

#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/errno.h>

#include <machine/bus.h>
#include <machine/resource.h>

#endif

#endif

/* local include file */
#include "../include/ioaccess.h"

#if (defined(MODULE) || defined(DIRECT_IO_ACCESS) || defined(KLD_MODULE))

/*
 *------------------------------------------------------------------------------
 * LEB-3010 Version V1.0
 *
 * The IO interface for Digital DIO is connected to Fintek SIO F75111RG.
 * Platform provide 4 digital input and 4 digital output. 
 * GPIO17-14 as input function, GPIO13-10 as output function
 * Refer to Fintek F75111RG datasheet for details.
 * The truth table is defined as below:
 * DIO GPIO pins as follows:
 *		IN		OUT
 * DIO		GP14		GP10
 * DIO		GP15		GP11
 * DIO		GP16		GP12
 * DIO		GP17		GP13
 *-----------------------------------------------------------------------------------
 */

/*
 * Device Depend Definition : Fintek F75111RG SIO
*/
#define sm_base	0x0400
#define slav_ads 0x6e

unsigned char read_F75111_reg(int reg, int sla1)
{
	outportb((sm_base+0x00),0xfe);//clr status
  	delay(10);	
  	outportb((sm_base+0x03),reg);//offset
  	delay(5);
  	outportb((sm_base+0x04),(sla1|0x01));
  	delay(5);  
  	outportb((sm_base+0x02),0x48);//byte write cmd
  	delay(20);//more delay for cmd finish 
  	outportb((sm_base+0x00),0xfe);//clr status
  	delay(10);
	return inportb(sm_base+0x05);//value 	
}


void write_F75111_reg(int reg, int value, int sla)
{
	outportb((sm_base+0x00),0xfe);//clr status
  	delay(10);	
  	outportb((sm_base+0x03),reg);//offset
  	delay(5);
  	outportb((sm_base+0x05),value);//value
  	delay(5);  
  	outportb((sm_base+0x04),(sla& 0xfe));
  	delay(5);  
  	outportb((sm_base+0x02),0x48);//byte write cmd
  	delay(20);//more delay for cmd finish 
  	outportb((sm_base+0x00),0xfe);//clr status
  	delay(10);
        return;
}

void dio_gpio_init(void)
{
	/* Enable GPIO10-12 function */		
	write_F75111_reg(0x03,read_F75111_reg(0x03, slav_ads) & 0xe0,slav_ads);
	
	/* Enable GPIO14-17 function */	
	write_F75111_reg(0x04,read_F75111_reg(0x04, slav_ads) & 0x9c,slav_ads);
	
	/* set GPO10-13 GPI14-17 */
	write_F75111_reg(0x10,(read_F75111_reg(0x10, slav_ads) & 0x00) | 0x0f,slav_ads);  
        
        return;
}
void dio_set_output(unsigned char out_value)
{
	write_F75111_reg(0x11,(read_F75111_reg(0x11, slav_ads) & 0x00) | out_value,slav_ads);	
        return;  
}

unsigned char dio_get_input(void)
{
        unsigned char tmp;
	tmp = (read_F75111_reg(0x12, slav_ads)& 0xf0) >> 4;
        return tmp;
}

#endif
Versteht dies jemand von euch? Daraus sollte sich auch direkt ein Script basteln lassen oder?

Antworten