#include #include #include #include #include #include #include #include "m_imp.h" /* pd includes */ #define REMOTE_SERVER_PORT 26482 static t_class *servo_class; typedef struct _servo { t_object x_obj; int x_fd; } t_servo; void *servo_new(void) { t_servo *x = (t_servo *)pd_new(servo_class); x->x_fd = -1; return (void *)x; } /****************************************************************************************/ /* called when a [connect hostname] is received */ /****************************************************************************************/ void servo_connect(t_servo *x, t_symbol *hostname) { int sd, sdhttp, rc, rchttp; char *value="1"; unsigned char *udpEnable="GET /interface.spi?udprcvr=1 HTTP/1.0\r\nHOST: 192.168.0.5\r\n"; struct sockaddr_in cliAddr, remoteServAddr; struct hostent *h; if (x->x_fd >= 0) { error("servo: already connected to %s", hostname->s_name); return; } /* get server IP address (no check if input is IP address or DNS name */ h = gethostbyname(hostname->s_name); if(h == NULL) { post("servo: unknown host"); return; } remoteServAddr.sin_family = h->h_addrtype; memcpy((char *) &remoteServAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length); remoteServAddr.sin_port = htons(REMOTE_SERVER_PORT); /***************************************************************************** /* This part creates the socket used to send the HTTP packets. This is why we /* use SOCK_STREAM. A particular HTTP request has to be sent to UDP-enable /* the controller. /* /* Socket creation */ sdhttp = socket(AF_INET, SOCK_STREAM, 0); if(sdhttp < 0) { post("servo: cannot open socket (http)"); return; } /* Bind any port */ cliAddr.sin_family = AF_INET; cliAddr.sin_addr.s_addr = htonl(INADDR_ANY); cliAddr.sin_port = htons(0); rchttp = bind(sdhttp, (struct sockaddr *) &cliAddr, sizeof(cliAddr)); if(rchttp < 0) { post("servo: cannot bind port (http)"); return; } /* Set options for this socket */ setsockopt(sdhttp, SOL_SOCKET, SO_REUSEPORT, value, sizeof(value)); /* Connect to server */ rchttp = connect(sdhttp, (struct sockaddr *) &remoteServAddr, sizeof(remoteServAddr)); if(rchttp < 0) { post("servo: cannot connect (http)"); return; } /* Send udp-enabling http request */ rchttp = send(sdhttp, udpEnable, strlen(udpEnable), 0); if(rchttp < 0) { perror("servo: cannot send data (http)"); return; } /* Close socket */ sys_closesocket(sdhttp); /***************************************************************************** /* This part creates the socket used to send the UDP packets. This is why we /* use SOCK_DGRAM. /* /* Socket creation */ sd = socket(AF_INET, SOCK_DGRAM, 0); if(sd < 0) { post("servo: cannot open socket (udp)"); return; } /* Bind any port */ cliAddr.sin_family = AF_INET; cliAddr.sin_addr.s_addr = htonl(INADDR_ANY); cliAddr.sin_port = htons(0); rc = bind(sd, (struct sockaddr *) &cliAddr, sizeof(cliAddr)); if(rc < 0) { post("servo: cannot bind port (udp)"); return; } /* Set options for this socket */ setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, value, sizeof(value)); /* Connect to server */ rc = connect(sd, (struct sockaddr *) &remoteServAddr, sizeof(remoteServAddr)); if(rc < 0) { post("servo: cannot connect (udp)"); return; } x->x_fd = sd; post("servo: connected to %s", hostname->s_name); } /****************************************************************************************/ /* called when a [go servo_num servo_angle] is received */ /****************************************************************************************/ void servo_go(t_servo *x, t_floatarg s, t_floatarg p) { unsigned char message[9]={03,252,25,255,01,01,01,0,0}; int rc, cont; if ((s < 1) || (s > 32)) { post("servo: servo number ranges from 1 to 32."); return; } if ((p < 1) || (p > 255)) { post("servo: servo position ranges from 1 to 255."); return; } /* format data */ cont = (s-1)/8+1; message[4] = cont; /* controller number */ message[5] = s-8*(cont-1); message[6] = p; rc = send(x->x_fd, message, 9, 0); if(rc < 0) post("servo: cannot send servo data"); } /****************************************************************************************/ /* called when a [disconnect] is received */ /****************************************************************************************/ void servo_disconnect(t_servo *x) { if (x->x_fd >= 0) { sys_closesocket(x->x_fd); x->x_fd = -1; } post("servo: disconnected"); } void servo_free(t_servo *x) { servo_disconnect(x); } void servo_setup(void) { servo_class = class_new(gensym("servo"), (t_newmethod)servo_new, (t_method)servo_free, sizeof(t_servo), CLASS_DEFAULT, A_GIMME, 0); class_addmethod(servo_class, (t_method)servo_connect, gensym("connect"), A_SYMBOL, 0); class_addmethod(servo_class, (t_method)servo_disconnect, gensym("disconnect"), 0); class_addmethod(servo_class, (t_method)servo_go, gensym("go"), A_DEFFLOAT, A_DEFFLOAT, 0); post("servo: Julien Jassaud (sojastar@wanadoo.fr)\nservo: ver: 0.5b"); }