| 1 | #if 0 | 
|---|
| 2 | Inter-driver communications tutorial - Dome Driver | 
|---|
| 3 | Copyright (C) 2007 Jasem Mutlaq (mutlaqja@ikarustech.com) | 
|---|
| 4 |  | 
|---|
| 5 | This library is free software; you can redistribute it and/or | 
|---|
| 6 | modify it under the terms of the GNU Lesser General Public | 
|---|
| 7 | License as published by the Free Software Foundation; either | 
|---|
| 8 | version 2.1 of the License, or (at your option) any later version. | 
|---|
| 9 |  | 
|---|
| 10 | This library is distributed in the hope that it will be useful, | 
|---|
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
| 13 | Lesser General Public License for more details. | 
|---|
| 14 |  | 
|---|
| 15 | You should have received a copy of the GNU Lesser General Public | 
|---|
| 16 | License along with this library; if not, write to the Free Software | 
|---|
| 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA | 
|---|
| 18 |  | 
|---|
| 19 | #endif | 
|---|
| 20 |  | 
|---|
| 21 | #include <stdio.h> | 
|---|
| 22 | #include <stdlib.h> | 
|---|
| 23 | #include <string.h> | 
|---|
| 24 | #include <stdarg.h> | 
|---|
| 25 | #include <math.h> | 
|---|
| 26 | #include <unistd.h> | 
|---|
| 27 | #include <time.h> | 
|---|
| 28 | #include <fcntl.h> | 
|---|
| 29 | #include <errno.h> | 
|---|
| 30 | #include <sys/stat.h> | 
|---|
| 31 | #include <sys/time.h> | 
|---|
| 32 | #include <sys/types.h> | 
|---|
| 33 | #include <sys/socket.h> | 
|---|
| 34 | #include <netinet/in.h> | 
|---|
| 35 | #include <netdb.h> | 
|---|
| 36 | #include <zlib.h> | 
|---|
| 37 |  | 
|---|
| 38 | #include "indidevapi.h" | 
|---|
| 39 | #include "eventloop.h" | 
|---|
| 40 | #include "indicom.h" | 
|---|
| 41 |  | 
|---|
| 42 | #define mydev           "Dome" | 
|---|
| 43 |  | 
|---|
| 44 | #define MAIN_GROUP      "Main" | 
|---|
| 45 | #define SNOOP_GROUP     "Snooped" | 
|---|
| 46 |  | 
|---|
| 47 | void closeDome(); | 
|---|
| 48 |  | 
|---|
| 49 | /* Connect/Disconnect */ | 
|---|
| 50 | static ISwitch PowerS[]                 = {{"CONNECT" , "Connect" , ISS_OFF, 0, 0},{"DISCONNECT", "Disconnect", ISS_ON, 0, 0}}; | 
|---|
| 51 | static ISwitchVectorProperty PowerSP    = { mydev, "CONNECTION" , "Connection", MAIN_GROUP, IP_RW, ISR_1OFMANY, 60, IPS_IDLE, PowerS, NARRAY(PowerS), "", 0}; | 
|---|
| 52 |  | 
|---|
| 53 | /* Dome Open/Close */ | 
|---|
| 54 | static ISwitch DomeS[]                  = {{"Open", "", ISS_ON, 0, 0}, {"Close", "", ISS_OFF, 0, 0}}; | 
|---|
| 55 | static ISwitchVectorProperty DomeSP     = { mydev, "Dome Status", "", MAIN_GROUP, IP_RW, ISR_1OFMANY, 0, IPS_IDLE, DomeS , NARRAY(DomeS), "", 0}; | 
|---|
| 56 |  | 
|---|
| 57 | /* The property we're trying to fetch from the rain driver. It's a carbon copy of the property define in rain.c, we initilize its structure here like any | 
|---|
| 58 | other local property, but we don't define it to client, it's only used internally within the driver. | 
|---|
| 59 |  | 
|---|
| 60 | MAKE SURE to set the property's device name to the device we're snooping on! If you copy/paste the property definition from the snooped driver | 
|---|
| 61 | don't forget to remove "mydev" and replace it with the driver name. | 
|---|
| 62 | */ | 
|---|
| 63 | static ILight RainL[]                   = {{"Status", "", IPS_IDLE, 0, 0}}; | 
|---|
| 64 | static ILightVectorProperty RainLP      = { "Rain", "Rain Alert", "", SNOOP_GROUP, IPS_IDLE, RainL , NARRAY(RainL), "", 0}; | 
|---|
| 65 |  | 
|---|
| 66 | void ISGetProperties (const char *dev) | 
|---|
| 67 | { | 
|---|
| 68 | /* MAIN_GROUP */ | 
|---|
| 69 | IDDefSwitch(&PowerSP, NULL); | 
|---|
| 70 | IDDefSwitch(&DomeSP, NULL); | 
|---|
| 71 |  | 
|---|
| 72 | /* Let's listen for Rain Alert property in the device Rain */ | 
|---|
| 73 | IDSnoopDevice("Rain", "Rain Alert"); | 
|---|
| 74 | } | 
|---|
| 75 |  | 
|---|
| 76 | void ISNewBLOB (const char *dev, const char *name, int sizes[], int blobsizes[], char *blobs[], char *formats[], char *names[], int n) {} | 
|---|
| 77 |  | 
|---|
| 78 | void ISSnoopDevice (XMLEle *root) | 
|---|
| 79 | { | 
|---|
| 80 |  | 
|---|
| 81 | IPState old_state = RainL[0].s; | 
|---|
| 82 |  | 
|---|
| 83 | /* If the "Rain Alert" property gets updated in the Rain device, we will receive a notification. We need to process the new values of Rain Alert and update the local version | 
|---|
| 84 | of the property.*/ | 
|---|
| 85 | if (IUSnoopLight(root, &RainLP) == 0) | 
|---|
| 86 | { | 
|---|
| 87 |  | 
|---|
| 88 | // If the dome is connected and rain is Alert */ | 
|---|
| 89 | if (PowerSP.s == IPS_OK && RainL[0].s == IPS_ALERT) | 
|---|
| 90 | { | 
|---|
| 91 | // If dome is open, then close it */ | 
|---|
| 92 | if (DomeS[0].s == ISS_ON) | 
|---|
| 93 | closeDome(); | 
|---|
| 94 | else | 
|---|
| 95 | IDMessage(mydev, "Rain Alert Detected! Dome is already closed."); | 
|---|
| 96 | } | 
|---|
| 97 | else if (old_state == IPS_ALERT && RainL[0].s != IPS_ALERT) | 
|---|
| 98 | IDMessage(mydev, "Rain threat passed. Opening the dome is now safe."); | 
|---|
| 99 |  | 
|---|
| 100 | } | 
|---|
| 101 |  | 
|---|
| 102 | } | 
|---|
| 103 |  | 
|---|
| 104 | void ISNewSwitch (const char *dev, const char *name, ISState *states, char *names[], int n) | 
|---|
| 105 | { | 
|---|
| 106 | /* ignore if not ours */ | 
|---|
| 107 | if (dev && strcmp (dev, mydev)) | 
|---|
| 108 | return; | 
|---|
| 109 |  | 
|---|
| 110 | /* Connection */ | 
|---|
| 111 | if (!strcmp (name, PowerSP.name)) | 
|---|
| 112 | { | 
|---|
| 113 | if (IUUpdateSwitch(&PowerSP, states, names, n) < 0) | 
|---|
| 114 | return; | 
|---|
| 115 |  | 
|---|
| 116 | PowerSP.s = IPS_OK; | 
|---|
| 117 |  | 
|---|
| 118 | if (PowerS[0].s == ISS_ON) | 
|---|
| 119 | IDSetSwitch(&PowerSP, "Dome is online."); | 
|---|
| 120 | else | 
|---|
| 121 | { | 
|---|
| 122 | PowerSP.s = IPS_IDLE; | 
|---|
| 123 | IDSetSwitch(&PowerSP, "Dome is offline."); | 
|---|
| 124 | } | 
|---|
| 125 |  | 
|---|
| 126 | return; | 
|---|
| 127 | } | 
|---|
| 128 |  | 
|---|
| 129 | /* Dome */ | 
|---|
| 130 | if (!strcmp (name, DomeSP.name)) | 
|---|
| 131 | { | 
|---|
| 132 |  | 
|---|
| 133 | if (PowerSP.s != IPS_OK) | 
|---|
| 134 | { | 
|---|
| 135 | IDMessage(mydev, "Dome is offline!"); | 
|---|
| 136 | return; | 
|---|
| 137 | } | 
|---|
| 138 |  | 
|---|
| 139 | if (IUUpdateSwitch(&DomeSP, states, names, n) < 0) | 
|---|
| 140 | return; | 
|---|
| 141 |  | 
|---|
| 142 | DomeSP.s = IPS_BUSY; | 
|---|
| 143 |  | 
|---|
| 144 | if (DomeS[0].s == ISS_ON) | 
|---|
| 145 | { | 
|---|
| 146 | if (RainL[0].s == IPS_ALERT) | 
|---|
| 147 | { | 
|---|
| 148 | DomeSP.s = IPS_ALERT; | 
|---|
| 149 | DomeS[0].s = ISS_OFF; | 
|---|
| 150 | DomeS[1].s = ISS_ON; | 
|---|
| 151 | IDSetSwitch(&DomeSP, "It is raining, cannot open dome."); | 
|---|
| 152 | return; | 
|---|
| 153 | } | 
|---|
| 154 |  | 
|---|
| 155 | IDSetSwitch(&DomeSP, "Dome is opening."); | 
|---|
| 156 | } | 
|---|
| 157 | else | 
|---|
| 158 | IDSetSwitch(&DomeSP, "Dome is closing."); | 
|---|
| 159 |  | 
|---|
| 160 | sleep(5); | 
|---|
| 161 |  | 
|---|
| 162 | DomeSP.s = IPS_OK; | 
|---|
| 163 |  | 
|---|
| 164 | if (DomeS[0].s == ISS_ON) | 
|---|
| 165 | IDSetSwitch(&DomeSP, "Dome is open."); | 
|---|
| 166 | else | 
|---|
| 167 | IDSetSwitch(&DomeSP, "Dome is closed."); | 
|---|
| 168 |  | 
|---|
| 169 | return; | 
|---|
| 170 | } | 
|---|
| 171 |  | 
|---|
| 172 | } | 
|---|
| 173 |  | 
|---|
| 174 | void ISNewText (const char *dev, const char *name, char *texts[], char *names[], int n) | 
|---|
| 175 | { | 
|---|
| 176 | /* ignore if not ours */ | 
|---|
| 177 | if (dev && strcmp (mydev, dev)) | 
|---|
| 178 | return; | 
|---|
| 179 |  | 
|---|
| 180 | /* suppress warning */ | 
|---|
| 181 | n=n; dev=dev; name=name; names=names; texts=texts; | 
|---|
| 182 | } | 
|---|
| 183 |  | 
|---|
| 184 |  | 
|---|
| 185 | void ISNewNumber (const char *dev, const char *name, double values[], char *names[], int n) {} | 
|---|
| 186 |  | 
|---|
| 187 | void closeDome() | 
|---|
| 188 | { | 
|---|
| 189 | DomeSP.s = IPS_BUSY; | 
|---|
| 190 |  | 
|---|
| 191 | IDSetSwitch(&DomeSP, "Rain Alert! Dome is closing..."); | 
|---|
| 192 |  | 
|---|
| 193 | sleep(5); | 
|---|
| 194 |  | 
|---|
| 195 | DomeS[0].s = ISS_OFF; | 
|---|
| 196 | DomeS[1].s = ISS_ON; | 
|---|
| 197 |  | 
|---|
| 198 | DomeSP.s = IPS_OK; | 
|---|
| 199 |  | 
|---|
| 200 | IDSetSwitch(&DomeSP, "Dome is closed."); | 
|---|
| 201 |  | 
|---|
| 202 |  | 
|---|
| 203 | } | 
|---|
| 204 |  | 
|---|