Há algum tempo atrás fiz um programa para controlar um velocimetro no Lintouch, o objetivo era ter o servidor SNMP pegando dados de um programa visual (GTK) e enviando estes mesmos dados para visualização no Lintouch.
Como tudo que não é documentado se perde, resolvi discutir a implementação aqui.
O MIB é simples:
UFRGS-MIB DEFINITIONS ::= BEGIN IMPORTS MODULE-IDENTITY, OBJECT-TYPE, Integer32, Counter32, IpAddress, enterprises FROM SNMPv2-SMI MODULE-COMPLIANCE, OBJECT-GROUP FROM SNMPv2-CONF; -- -- A brief description and update information about this mib. -- ufrgs MODULE-IDENTITY LAST-UPDATED "0104010000Z" -- 01 Apr 2001, midnight ORGANIZATION "UFRGS" CONTACT-INFO " Author: Alan Carvalho de Assis UFRGS, Departamento de Engenharia Eletrica Av. Oswaldo Aranha Porto Alegre BRAZIL email: acassis@gmail.com tel: +55-051-3316-3561" DESCRIPTION "MIB Agent for Baja-by-Wire" ::= { enterprises 12619 } -- the meters group meters OBJECT IDENTIFIER ::= { ufrgs 1 } reserved OBJECT IDENTIFIER::= { ufrgs 2 } -- -- The Speed (to speedometer) -- speed OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-write STATUS current DESCRIPTION "The speed variable." DEFVAL { 0 } ::= { meters 1 } -- -- The RPM (to tachometer) -- rpm OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-write STATUS current DESCRIPTION "The engine rotation variable." DEFVAL { 0 } ::= { meters 2 } -- -- The temperature variable -- temperature OBJECT-TYPE SYNTAX Integer32 MAX-ACCESS read-write STATUS current DESCRIPTION "The engine temperature." DEFVAL { 0 } ::= { meters 3 } END
Na inicialização do MIB (init-ufrgs) eu crio uma área de memória compartilhada:
typedef struct { int speed; int rpm; int temperature; }meter; #define SHM_SIZE 12 /* 12 bytes (meter struct size) */ static u_long speed; static u_long rpm; static u_long temperature; meter *m; void init_ufrgs(void) { static oid speed_oid[] = { 1,3,6,1,4,1,12619,1,1 }; static oid rpm_oid[] = { 1,3,6,1,4,1,12619,1,2 }; static oid temperature_oid[] = { 1,3,6,1,4,1,12619,1,3 }; key_t key; int shmid; int *data; int mode; FILE *f; /* create the identifier file*/ if((f=fopen("/tmp/meter","w")) == NULL) { perror("fopen"); exit(1); } /* close it*/ fclose(f); /* make the key: */ if ((key = ftok("/tmp/meter", 'R')) == -1) { perror("ftok"); exit(1); } /* connect to (and possibly create) the segment: */ if ((shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT)) == -1) { perror("shmget"); exit(1); } /* attach to the segment to get a pointer to it: */ data = shmat(shmid, (void *)0, 0); m = (meter *) data; if (data == (int *)(-1)) { perror("shmat"); exit(1); } DEBUGMSGTL(("ufrgs", "Initializing\n")); }
E na requisição MODE_GET de cada variável lemos o valor que nos foi enviado pela aplicação GTK (discutida abaixo):
case MODE_GET: speed = (u_long) m->speed; snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, (u_char *) &speed, sizeof(speed)); break;
Na aplicação GTK abrimos a região de memória (mesmo código de init_ufrgs) compartilhada e escrevemos os valores lidos dos sliders:
void on_hscale1_value_changed(GtkRange *range, gpointer user_data){ gdouble vel; vel = gtk_range_get_value(range); m->speed = (int)vel; } void on_hscale2_value_changed(GtkRange *range, gpointer user_data){ gdouble rot; rot = gtk_range_get_value(range); m->rpm = (int)rot; } void on_hscale3_value_changed(GtkRange *range, gpointer user_data){ gdouble temp; temp = gtk_range_get_value(range); m->temperature = (int)temp; }