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;
}