Xpl-vmc.c
De MicElectroLinGenMet.
Source du programme xpl-vmc
Programme C pour piloter une VMC par bus 1-wire et messages Xpl.
/* xpl-vmc */ /* 5/10/2009 Arrét/marche lente/rapide de la VMC en fonction de l'humidité salle de bain (sonde Oregon) ----------------------------------------------------------------------------------- Messages xPL utilisés: En écoute état senseur: SENSOR.BASIC sensor.basic { device='thgr228n.32' type='humidity' current='43' string='comfortable' } Commande/statut état VMC: HVAC.BASIC (heating, ventilation and air-conditioning) devices http://xplproject.org.uk/wiki/index.php/Schema_-_HVAC ----------------------------------------------------------------------------------- Arrét/marche lente/rapide de la VMC $ xpl-sender -m xpl-cmnd -c hvac.basic command=fan-mode zone=SdB mode=Off/OnHigh/OnLow/AutoHigh/AutoLow ----------------------------------------------------------------------------------- Envoie de message Trigger en response aux messages hvac.basic. hvac.zone { zone=id hvac-mode= fan-mode= timer-mode= hvac-state= fan-state= temperature=# } HVAC.ZONE signale changement état ventilation. xpl-trig { hop=1 source=domos-xplvmc.vesta target=* } hvac.zone { zone=SdB fan-mode=Off/OnHigh/OnLow/AutoHigh/AutoLow humidity=h%sdb } ----------------------------------------------------------------------------------- Demande état de la zone SdB $ xpl-sender -m xpl-cmnd -c hvac.request request=zone zone=SdB hvac.request { request=gateinfo|zonelist|zoneinfo|zone|setpoint|timer|runtime|fantime zone=id [setpoint=] [state=] } --------------- Envoie de message Status en response aux messages hvac.request. xpl-stat { hop=1 source=domos-xplvmc.vesta target=* } hvac.zone { zone=SdB fan-mode=Off/OnHigh/OnLow/AutoHigh/AutoLow humidity=h%sdb } ----------------------------------------------------------------------------------- Log du programme en fonctionnement. Oct 18 19:07:19 vesta xpl-vmc[789]: Démarrage ... Oct 18 20:03:11 vesta xpl-vmc[789]: Humidité SdB trop élévée ! Oct 18 20:03:11 vesta xpl-vmc[789]: Commande VMC en mode: 2. Oct 18 20:55:11 vesta xpl-vmc[789]: Humidité SdB revenue à la normale ! Oct 18 20:55:11 vesta xpl-vmc[789]: Commande VMC en mode: 1. */ //--------------------------------------------------------------------------------- #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <time.h> #include <syslog.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/un.h> #include <signal.h> #include <owcapi.h> #include <xPL.h> #include "xpl-vmc.h" #define ON '1' #define OFF '0' #define VRAI 1 #define FAUX 0 // Déclarations gestion programme int finprog = 0 ; int debug = 0 ; // Déclarations pour l'heure time_t td; struct tm *dc; char sdate[12]; char sheure[10]; // Déclarations pour xPL. #define XPL_VERSION "20091005" xPL_ServicePtr DomosService ; xPL_MessagePtr DomosMessageStat ; xPL_MessagePtr DomosMessageTrig ; // Déclarations pour la sonde #define SONDESDB "thgr228n.32" char svalhumidity[4] = "0" ; // Déclarations pour gestion VMC int autovmc = VRAI ; int stopvmc = FAUX ; int speed2vmc = FAUX ; // Déclarations pour OWFS. #define OWHOST "localhost:4304" #define OWOUTPUTVMCSTOP "/12.29435F000000/PIO.A" #define OWOUTPUTVMCSPEED2 "/12.8B515F000000/PIO.A" /* ------------------------------------------------------------------------------------ */ /* Fonctions xPL */ /* ------------------------------------------------------------------------------------ */ int init_xpl(void) { //xPL_setDebugging(TRUE) ; // Start xPL up if ( !xPL_initialize(xPL_getParsedConnectionType()) ) return 0 ; // Create a service DomosService = xPL_createService("domos", "xplvmc", "vesta"); xPL_setServiceVersion(DomosService, XPL_VERSION); // Add responder(s) // Ajout fonction écoute sensor.basic (état senseur SdB) xPL_addServiceListener(DomosService, DomosMessageSensorBasicHandler, xPL_MESSAGE_TRIGGER, "sensor", "basic", NULL) ; // Ajout fonction écoute hvac.basic (commande VMC) xPL_addServiceListener(DomosService, DomosMessageHvacBasicHandler, xPL_MESSAGE_COMMAND, "hvac", "basic", NULL) ; // Create a message to send DomosMessageStat = xPL_createBroadcastMessage(DomosService, xPL_MESSAGE_STATUS) ; DomosMessageTrig = xPL_createBroadcastMessage(DomosService, xPL_MESSAGE_TRIGGER) ; // Enable the service xPL_setServiceEnabled(DomosService, TRUE); return 1 ; } /* ------------------------------------------------------------------------------------ */ // Traite message sensor.basic (trig) // sensor.basic { device='thgr228n.32' type='humidity' current='45' string='comfortable' } void DomosMessageSensorBasicHandler(xPL_ServicePtr theService, xPL_MessagePtr theMessage, xPL_ObjectPtr userValue) { xPL_NameValueListPtr ListNomsValeursPtr ; char device[255] ; char type[255] ; char mode[255] ; float valhumidity ; if ( (autovmc) || (! stopvmc) ) { ListNomsValeursPtr = xPL_getMessageBody(theMessage) ; strcpy(device, (xPL_getNamedValue(ListNomsValeursPtr, "device")) ) ; if ( strstr(device, SONDESDB) != NULL ) { strcpy(type, (xPL_getNamedValue(ListNomsValeursPtr, "type")) ) ; if ( strstr(type, "humidity") != NULL ) { if (debug) PrintMessageInfo(theMessage, ListNomsValeursPtr) ; strcpy(svalhumidity, (xPL_getNamedValue(ListNomsValeursPtr, "current")) ) ; valhumidity = atoi(svalhumidity) ; if ( ( ! speed2vmc) && (valhumidity > 65) ) { syslog(LOG_INFO, "Humidité SdB trop élévée (%f%%) !", valhumidity) ; if ( setmodevmc(2) ) SendHvacZoneXpl("trig", "OnHigh", svalhumidity) ; } if ( ( speed2vmc) && (valhumidity < 64) ) { syslog(LOG_INFO, "Humidité SdB revenue à la normale (%f%%) !", valhumidity) ; if ( setmodevmc(1) ) SendHvacZoneXpl("trig", "OnLow", svalhumidity) ; } } } } } /* ------------------------------------------------------------------------------------ */ // Traite message hvac.basic (cmd) // hvac.basic command=fan-mode zone=SdB mode=Off/OnHigh/OnLow/AutoHigh/AutoLow void DomosMessageHvacBasicHandler(xPL_ServicePtr theService, xPL_MessagePtr theMessage, xPL_ObjectPtr userValue) { xPL_NameValueListPtr ListNomsValeursPtr ; char commande[255] ; char zone[255] ; char mode[255] ; ListNomsValeursPtr = xPL_getMessageBody(theMessage) ; strcpy(commande, (xPL_getNamedValue(ListNomsValeursPtr, "command")) ) ; if ( strstr(commande, "fan-mode") != NULL ) { if (debug) PrintMessageInfo(theMessage, ListNomsValeursPtr) ; strcpy(zone, (xPL_getNamedValue(ListNomsValeursPtr, "zone")) ) ; if ( strstr(zone, "SdB") != NULL ) { strcpy(mode, (xPL_getNamedValue(ListNomsValeursPtr, "mode")) ) ; if ( strstr(mode, "Off") != NULL ) { if ( setmodevmc(0) ) SendHvacZoneXpl("trig", "Off", svalhumidity) ; } else if ( strstr(mode, "OnLow") != NULL ) { if ( setmodevmc(1) ) SendHvacZoneXpl("trig", "OnLow", svalhumidity) ; } //else } } } /* ------------------------------------------------------------------------------------ */ /* Envoie messages */ /* ------------------------------------------------------------------------------------ */ // Envoi message: xpl-stat/xpl-trig hvac.zone (état vmc) void SendHvacZoneXpl(char *msgtype, char *mode, char *hum) { if (strcmp(msgtype, "stat") == 0) { xPL_setSchema(DomosMessageStat, "hvac", "zone"); // Install the value(s) and send the message xPL_setMessageNamedValue(DomosMessageStat, "zone", "SdB"); xPL_setMessageNamedValue(DomosMessageStat, "fan-mode", mode); xPL_setMessageNamedValue(DomosMessageStat, "humidity", hum); // Broadcast the message xPL_sendMessage(DomosMessageStat); } else { xPL_setSchema(DomosMessageTrig, "hvac", "zone"); // Install the value(s) and send the message xPL_setMessageNamedValue(DomosMessageTrig, "zone", "SdB"); xPL_setMessageNamedValue(DomosMessageTrig, "fan-mode", mode); xPL_setMessageNamedValue(DomosMessageTrig, "humidity", hum); // Broadcast the message xPL_sendMessage(DomosMessageTrig); } } /* ------------------------------------------------------------------------------------ */ // Affiche sur sdtout message xPL reçu (pour debug) void PrintMessageInfo(xPL_MessagePtr theMessage, xPL_NameValueListPtr ListNomsValeursPtr) { xPL_NameValuePairPtr NomValeurPtr = NULL; int NameValueIndex ; int NameValueCount ; printf("Received Message from %s-%s.%s type ", xPL_getSourceVendor(theMessage), xPL_getSourceDeviceID(theMessage), xPL_getSourceInstanceID(theMessage)); switch(xPL_getMessageType(theMessage)) { case xPL_MESSAGE_COMMAND: printf("xpl-cmnd "); break; case xPL_MESSAGE_STATUS: printf("xpl-stat "); break; case xPL_MESSAGE_TRIGGER: printf("xpl-trig "); break; default: printf("UNKNOWN "); break; } printf("for %s.%s: ", xPL_getSchemaClass(theMessage), xPL_getSchemaType(theMessage)); // Write Name/Value Pairs received out NameValueCount = xPL_getNamedValueCount(ListNomsValeursPtr) ; for (NameValueIndex = 0; NameValueIndex < NameValueCount; NameValueIndex++) { NomValeurPtr = xPL_getNamedValuePairAt(ListNomsValeursPtr, NameValueIndex); printf("%s=", NomValeurPtr->itemName); /* Write data content out */ if (NomValeurPtr->itemValue != NULL) printf("'%s' ", NomValeurPtr->itemValue); } printf("\n") ; } /* ------------------------------------------------------------------------------------ */ void shutdown_xpl(void) { xPL_setServiceEnabled(DomosService, FALSE) ; xPL_releaseService(DomosService) ; xPL_shutdown() ; } /* ------------------------------------------------------------------------------------ */ /* Fonction OW */ /* ------------------------------------------------------------------------------------ */ int setowoutput(char *output, char val) { if (debug) printf("Output=%s, val=%c\n", output, val) ; if ( OW_put(output, &val, 1) < 0 ) { sleep(1) ; if ( OW_put(output, &val, 1) < 0 ) // Deuxième essai. { syslog(LOG_ERR,"Erreur écriture senseur %s (essai 2) : %s\n", output, strerror(errno)); return 0 ; } } return 1 ; } /* ------------------------------------------------------------------------------------ */ /* Fonction commande VMC (Off=0 /OnLow=1 /OnHigh=2) */ /* ------------------------------------------------------------------------------------ */ int setmodevmc(int speed) { syslog(LOG_INFO, "Commande VMC en mode: %d.", speed) ; switch (speed) { case 0: if ( setowoutput(OWOUTPUTVMCSTOP, ON) ) { stopvmc = VRAI ; return 1 ; } else return 0 ; break ; case 1: if (stopvmc) if ( ! setowoutput(OWOUTPUTVMCSTOP, OFF) ) return 0 ; stopvmc = FAUX ; if ( setowoutput(OWOUTPUTVMCSPEED2, OFF) ) { speed2vmc = FAUX ; return 1 ; } else return 0 ; break; case 2: if (stopvmc) if ( ! setowoutput(OWOUTPUTVMCSTOP, OFF) ) return 0 ; stopvmc = FAUX ; if ( setowoutput(OWOUTPUTVMCSPEED2, ON) ) { speed2vmc = VRAI ; return 1 ; } else return 0 ; break; } return 0 ; } /* ------------------------------------------------------------------------------------ */ /* Fonctions interruptions */ /* ------------------------------------------------------------------------------------ */ void init_interruptions_signal(void) { signal(SIGHUP, &signal_handler); // Intercepte les signaux pour quitter le prog. proprement. signal(SIGINT, &signal_handler); // Fonction 'signal_handler' appelée. signal(SIGTERM, &signal_handler); signal(SIGQUIT, &signal_handler); } /* ------------------------------------------------------------------------------------ */ void signal_handler(int signum) { switch(signum) { case SIGINT: case SIGQUIT: case SIGTERM: syslog(LOG_INFO, "Abandon programme demandé. !") ; finprog = 1 ; break; case SIGHUP: syslog(LOG_INFO, "Réactivation programme demandée. !") ; break ; } } /* ------------------------------------------------------------------------------------ */ /* MAIN */ /* ------------------------------------------------------------------------------------ */ int main ( int argc, char ** argv ) { init_interruptions_signal() ; openlog("xpl-vmc", LOG_PID, LOG_USER) ; syslog(LOG_INFO, "Démarrage ...") ; // Init xPL. if ( ! init_xpl() ) { syslog(LOG_ERR, "Erreur lancement xPL ! "); closelog() ; exit(1) ; } if ( OW_init(OWHOST) != 0) { syslog(LOG_ERR, "Erreur init OWFS : %s\n", strerror(errno)) ; OW_finish() ; exit(1) ; } // Boucle principale. do { xPL_processMessages(100) ; usleep(10000) ; } while (! finprog) ; setmodevmc(1) ; // Vitesse VMC normale. // Fermeture xPL. syslog(LOG_INFO, "Arrêt couche xPL !") ; shutdown_xpl() ; syslog(LOG_INFO, "Arrêt connexion OWFS !") ; OW_finish() ; syslog(LOG_INFO, "Fin programme.") ; closelog() ; exit (0) ; } /* ------------------------------------------------------------------------------------ */