1
2
3 /*----------------------------------------------------------------------------+
4 | |
5 | X10 Module Attributes for HEYU |
6 | Copyright 2004-2008 Charles W. Sullivan |
7 | |
8 | |
9 | As used herein, HEYU is a trademark of Daniel B. Suthers. |
10 | X10, CM11A, and ActiveHome are trademarks of X-10 (USA) Inc. |
11 | SwitchLinc and LampLinc are trademarks of Smarthome, Inc. |
12 | The author is not affiliated with any of these entities. |
13 | |
14 | Charles W. Sullivan |
15 | Co-author and Maintainer |
16 | Greensboro, North Carolina |
17 | Email ID: cwsulliv01 |
18 | Email domain: -at- heyu -dot- org |
19 | |
20 +----------------------------------------------------------------------------*/
21
22 /*
23 * This program is free software: you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License as published by
25 * the Free Software Foundation, either version 3 of the License, or
26 * (at your option) any later version.
27 *
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program. If not, see <http://www.gnu.org/licenses/>.
35 */
36
37 #include <stdio.h>
38 #if defined(SYSV) || defined(FREEBSD) || defined(OPENBSD)
39 #include <string.h>
40 #else
41 #include <strings.h>
42 #endif
43 #include <stdlib.h>
44 #include <ctype.h>
45 #include "process.h"
46 #include "oregon.h"
47
48 /* Standard module attribute/response definitions for cflags */
49 /* Basic function codes 0-6 (maintain this order) */
50 #define UNOFF 0x00000001 /* All Units Off */
51 #define LION 0x00000002 /* All Lights ON */
52 #define MON 0x00000004 /* Simple module ON */
53 #define MOFF 0x00000008 /* Simple module OFF */
54 #define DIM 0x00000010 /* Dim 1-22 */
55 #define BRI 0x00000020 /* Bright 1-22 */
56 #define LIOFF 0x00000040 /* All Lights OFF */
57 /* Other attributes */
58 #define ALLON 0x00000080 /* All Units On */
59 #define STDX10 0x00000100 /* Standard X10 */
60 #define PRESET 0x00000200 /* Preset 1-32 */
61 #define BRIB4DIM 0x00000400 /* If OFF, full Brightness before dimming */
62 #define STAREQ 0x00000800 /* Responds to Status Request */
63 #define STAON 0x00001000 /* Sends StatusOn ack */
64 #define STAOFF 0x00002000 /* Sends StatusOff ack */
65 #define LIONFULL 0x00004000 /* All Lights ON -> Full brightness */
66 #define ONFULL 0x00008000 /* ON -> Full (or option) brightness */
67 #define ONFULLOFF 0x00010000 /* ON -> Full brightness if Off */
68 #define RESUME 0x00020000 /* ON resumes previous level */
69 #define RESUMEDIM 0x00040000 /* Dim/Bright first resumes previous level */
70 #define LIONUNAD 0x00080000 /* AllLightsOn unaddresses the module */
71 #define LIOFFUNAD 0x00100000 /* AllLightsOff unaddresses the module */
72 #define TARG 0x00200000 /* Is a target instead of a module */
73 #define EXC16 0x00400000 /* Last unit turns On (all others turn off) */
74 #define EXC8 0x00800000 /* Last unit turns On (others in group of 8 turn off) */
75 #define EXC4 0x01000000 /* Last unit turns On and others in group of 4 turn off) */
76 #define VDATA 0x02000000 /* Virtual data repository */
77 #define PLCSENSOR 0x04000000 /* PLC Sensor */
78 #define ADDRESSED 0x08000000 /* Has standard address */
79 #define PHYS 0x10000000 /* Is a physical module */
80 #define ONOFFUNAD 0x20000000 /* On or Off unaddresses the module (ACT bug) */
81
82 /* NOTE: Attributes STDX10, PRESET, and EXT3SW/EXT3DIM are */
83 /* mutually incompatible. */
84
85 /* Extended code module attributes for xflags */
86 /* (Group reference characteristic types are mutually incompatible.) */
87 #define XNON 0
88 #define X3SW 0x00000001 /* Extended codes Type 3 (switch only) */
89 #define X3DIM 0x00000002 /* Extended codes Type 3 with preset dim 0-63 */
90 #define X0SH 0x00000004 /* Extended code Type 0 shutter control */
91 #define X3GEXEC 0x00000008 /* Supports Extended Group Exec command */
92 #define X3GRC1 0x00000010 /* Group reference characteristic Type 1 (LM14A, AM14A) */
93 #define X3GRC2 0x00000020 /* Group reference characteristic Type 2 (LM465-1) */
94 #define X3GRC3 0x00000040 /* Group reference characteristic Type 3 (WS467-1) */
95 #define X3GRC4 0x00000080 /* Group reference characteristic Type 4 */
96 #define X3GOFF 0x00000100 /* Extended Group Off */
97 #define X3GOFFEX 0x00000200 /* Extended Group Off acts like Group Exec */
98 #define X3GBD 0x00000400 /* Extended Group Bright/Dim */
99 #define X3GBDFULL 0x00000800 /* Ext Grp Bri/Dim resumes, or brightens full if prev at level 0 */
100 #define X3STAT 0x00001000 /* Extended code status, i.e., 2-way */
101 #define X3GREM 0x00002000 /* Extended Group Remove works */
102 #define X0PRESET 0x00004000 /* Extended code Type 0 shutter preset */
103
104 /* Virtual model attributes for vflags */
105 #define VNON 0
106 #define VSTD 0x00000001 /* X10 Standard */
107 #define VENT 0x00000002 /* X10 Entertainment */
108 #define VSEC 0x00000004 /* X10 Security */
109 #define VRFXS 0x00000008 /* RFX Sensor */
110 #define VRFXM 0x00000010 /* RFX Meter */
111 #define VDMX 0x00000020 /* Digimax */
112 #define VORE 0x00000040 /* Oregon */
113 #define VKAKU 0x00000080 /* KAKU */
114
115 /* KaKu model attributes for kflags */
116 #define KOFF 0x00000001 /* Off */
117 #define KON 0x00000002 /* On */
118 #define KGOFF 0x00000004 /* Group Off */
119 #define KGON 0x00000008 /* Group On */
120 #define KPRE 0x00000010 /* Preset */
121 #define KGPRE 0x00000020 /* Group Preset */
122 #define KRESUME 0x00000040 /* Resume */
123 #define KPHYS 0x00000080 /* Physical module */
124
125 /* Module max dim levels */
126 #define MXL0 0
127 #define MXLS 210 /* Standard X10 modules 0-210 */
128 #define MXLP 31 /* Preset modules 0-31 (zero-base) */
129 #define MXLE 62 /* Extended code Type 3 dimmer modules 0-62 */
130 #define MXLEA 63 /* Extended code Type 3 appliance modules 0,63 */
131 #define MXLS0 25 /* Extended code Type 0 shutters 0-25 */
132 #define MXLV 255 /* Virtual modules 0-255 */
133 #define MXLK 15 /* KAKU modules 0-15 */
134
135 /* Standard module type attributes for cflags . To add a new module type, */
136 /* "OR" together its attributes here and add an entry in the modules */
137 /* table below. (Keep the table uncluttered, for future additions.) */
138 #define NOMATT 0
139 #define BASIC (UNOFF | MON | MOFF | ALLON | ADDRESSED | PHYS)
140 #define ACTBASIC (STDX10 | MON | MOFF | ALLON | ADDRESSED | PHYS | STAON | STAOFF | STAREQ)
141 #define ACTBUG (ACTBASIC | ONOFFUNAD)
142
143 #define STDAM (BASIC | STDX10)
144 #define STDLM (STDAM | DIM | BRI | BRIB4DIM | LION | ONFULLOFF)
145 #define STDWS (STDLM | LIOFF)
146 #define AMS (STDAM | STAON | STAOFF | STAREQ)
147 #define LMS (STDLM | STAON | STAOFF | STAREQ)
148 #define SIREN (STDAM | LION )
149 #define REM2 (STDX10 | TARG | MON | MOFF)
150 #define REM3 (STDX10 | TARG | MOFF | BRI | DIM)
151 #define REM4 (STDX10 | TARG | MON | MOFF | BRI | DIM)
152 #define REM6 (STDX10 | TARG | MON | MOFF | BRI | DIM | LION | UNOFF)
153
154 #define LM15A (STDAM | LION | LIONFULL | LIOFF | LIONUNAD | LIOFFUNAD)
155 #define XPS3 (STDAM | LION | LIONFULL | LIOFF)
156 #define XPD3 (STDLM | LIOFF)
157
158 #define PR511 (STDAM | STAON | STAOFF | STAREQ | LION | LIONFULL | LIOFF)
159
160 #define AM14A (BASIC | ALLON | STAON | STAOFF | STAREQ)
161 #define LM14A (AM14A | DIM | BRI | LION | LIOFF | RESUME | RESUMEDIM | LIOFFUNAD)
162
163 #define SL1AM (BASIC)
164 #define SL2AM (SL1AM | STAREQ)
165
166 #define SL1LM (BASIC | PRESET | DIM | BRI | LION | LIOFF | ONFULL)
167 #define SL2LM (SL1LM | STAREQ)
168
169 #define LL1LM (BASIC | PRESET | DIM | BRI | LION | LIOFF | LIONFULL | ONFULL)
170 #define LL2LM (LL1LM | STAREQ)
171 #define AMEXC16 (STDAM | EXC16)
172 #define AMEXC8 (STDAM | EXC8 )
173 #define AMEXC4 (STDAM | EXC4 )
174 #define CAMEXC4 (STDX10 | EXC4 | MON | MOFF | ADDRESSED | PHYS)
175 #define VIRT4 (TARG | MON | MOFF | BRI | DIM)
176 #define SHUT0 (MON | MOFF | RESUME | PHYS)
177 #define VIRTUAL (TARG | VDATA)
178 #define PALMPAD (TARG | MON | MOFF | BRI | DIM)
179 #define KEYCHAIN (TARG | MON | MOFF)
180 #define ONLYON (TARG | MON)
181 #define ONLYOFF (TARG | MOFF)
182 #define PLCSEN (TARG | MON | MOFF | ADDRESSED | PLCSENSOR)
183 #define MOTION (TARG | MON | MOFF)
184
185 #define LM_1 (BASIC | DIM | BRI | LION | LIOFF | RESUMEDIM | LIOFFUNAD)
186 #define WS_1 (BASIC | DIM | BRI | LION | RESUME)
187
188 /* Extended module type attributes for xflags */
189
190 #define XAM14A (X3SW | X3GEXEC | X3GRC1 | X3GOFFEX | X3STAT | X3GREM)
191 #define XLM14A (X3SW | X3GEXEC | X3DIM | X3GRC1 | X3GOFFEX | X3STAT | X3GREM)
192 #define XLM_1 (X3SW | X3GEXEC | X3DIM | X3GRC2 | X3GOFF | X3GBD | X3GBDFULL)
193 #define XWS_1 (X3SW | X3GEXEC | X3DIM | X3GRC3 | X3GOFFEX | X3GREM)
194 #define XSHUT0 (X0SH)
195
196 /* KaKu module type attributes */
197 #define KAM (KOFF | KON | KGOFF | KGON)
198 #define KLM (KAM | KPRE | KGPRE | KRESUME)
199
200 /* Module option functions */
201 int opt_onlevel(), opt_sremote(), opt_kremote(), opt_sensor(), opt_svsensor(), opt_ds90(), opt_sd90(),
202 opt_ur81a(), opt_ux17a(), opt_guru(), opt_aux(), opt_rfxsensor(), opt_rfxold(), opt_act(), opt_defer(),
203 opt_rfxtemp(),
204 opt_rfxpulse(), opt_rfxcount(), opt_rfxpower(), opt_rfxwater(), opt_rfxgas(),
205 opt_sd10(), opt_plcsensor(), opt_gb10(), opt_jam(), opt_digimax(),
206 opt_oreTH1(), opt_oreTH2(), opt_oreTH3(), opt_oreTH4(), opt_oreTH5(), opt_oreTH6(),
207 opt_oreTemp1(), opt_oreTemp2(), opt_oreTemp3(), opt_oreTHB1(), opt_oreTHB2(), opt_oreWeight1(),
208 opt_oreTemu(), opt_oreTHemu(), opt_oreTHBemu(), opt_x10std(), opt_oreignore(), opt_elsElec1(),
209 opt_bmb_sd18(),
210 opt_secignore(), opt_visonic(),
211 opt_oreWind1(), opt_oreWind2(), opt_oreWind3(),
212 opt_oreRain1(), opt_oreRain2(), opt_oreRain3(),
213 opt_oreUV1(), opt_oreUV2(), opt_kaku(), opt_owlElec2(), opt_owlElec2new(), opt_owlElec2rev();
214
215 /* Decoder functions for modules */
216 int fn_ds10a(), fn_ds90(), fn_ms10a(), fn_sh624(), fn_kr10a(), fn_ur81a(),
217 fn_guru(), fn_rfxsensor(),
218 fn_rfxpulse(), fn_rfxcount(), fn_rfxpower(), fn_rfxwater(), fn_rfxgas(),
219 fn_sd10(), fn_sd90(), fn_ms90(), fn_ds18(), fn_gb10(), fn_svdata(), fn_jam(),
220 fn_kr15a(), fn_kr18(), fn_dm10(), fn_bmb_sd18(), fn_visonic();
221
222 extern int ore_maxmin_temp ( ALIAS *, int, char **, int * );
223 extern int ore_maxmin_rh ( ALIAS *, int, char **, int * );
224 extern int ore_maxmin_bp ( ALIAS *, int, char **, int * );
225 extern double celsius2temp ( double, char, double);
226 int sensor_timeout ( ALIAS *, int, char **, int * );
227
228
229
230 struct modules_st {
231 char *label; /* Case insensitive */
232 int maxlevel;
233 unsigned long vflags; /* Virtual attributes */
234 unsigned long cflags; /* Standard attributes */
235 unsigned long xflags; /* Extended code attributes */
236 int (*addopt_func)();
237 int (*xlate_func)();
238 } modules[] = {
239 {"NONE", MXLS, VNON, NOMATT, 0, NULL, NULL }, /* Has no attributes */
240 {"StdAM", MXLS, VNON, STDAM, 0, NULL, NULL }, /* Standard X10 1-way Appliance Module */
241 {"AM", MXLS, VNON, STDAM, 0, NULL, NULL }, /* Standard X10 1-way Appliance Module */
242 {"AM486", MXLS, VNON, STDAM, 0, NULL, NULL }, /* Standard X10 1-way Appliance Module */
243 {"AM12", MXLS, VNON, STDAM, 0, NULL, NULL }, /* Marmitek Standard X10 1-way Appliance Module */
244 {"PAM01", MXLS, VNON, STDAM, 0, NULL, NULL }, /* Standard X10 1-way Appliance Module */
245 {"AM466", MXLS, VNON, STDAM, 0, NULL, NULL }, /* Standard X10 1-way Appliance Module */
246 {"PAM02", MXLS, VNON, STDAM, 0, NULL, NULL }, /* Standard X10 1-way Appliance Module */
247 {"SR227", MXLS, VNON, STDAM, 0, NULL, NULL }, /* Standard X10 1-way Appliance Module */
248 {"PA011", MXLS, VNON, STDAM, 0, NULL, NULL }, /* Standard X10 1-way Appliance Module */
249 {"AMS", MXLS, VNON, AMS, 0, opt_defer, NULL }, /* 2-way Appliance Module */
250 {"RAIN8II", MXLS, VNON, AMS, 0, opt_defer, NULL }, /* Rain8II 2-way Irrigation Module */
251 {"RR501", MXLS, VNON, AMS, 0, NULL, NULL }, /* X10 Transceiver/Switch */
252 {"PAT01", MXLS, VNON, AMS, 0, NULL, NULL }, /* X10 Transceiver/Switch */
253 {"ACTAMS", MXLS, VNON, ACTBASIC, 0, opt_act, NULL}, /* ACT programmable appliance module */
254 {"RS114", MXLS, VNON, ACTBASIC, 0, opt_act, NULL}, /* ACT programmable appliance module */
255 {"ACTAMSBUG", MXLS, VNON, ACTBUG, 0, opt_act, NULL}, /* ACT as above with On/Off unaddress bug */
256 {"RF234", MXLS, VNON, ACTBUG, 0, opt_act, NULL}, /* ACT as above with On/Off unaddress bug */
257 {"StdLM", MXLS, VNON, STDLM, 0, NULL, NULL }, /* Standard X10 1-way Lamp Module */
258 {"LM", MXLS, VNON, STDLM, 0, NULL, NULL }, /* Standard X10 1-way Lamp Module */
259 {"LM465", MXLS, VNON, STDLM, 0, NULL, NULL }, /* Standard X10 1-way Lamp Module */
260 {"LM12", MXLS, VNON, STDLM, 0, NULL, NULL }, /* Marmitek X10 1-way Lamp Module */
261 {"LM465-1", MXLE, VNON, LM_1, XLM_1, NULL, NULL }, /* Redesigned (2007) X10 1-way Lamp Module */
262 {"LM-1", MXLE, VNON, LM_1, XLM_1, NULL, NULL }, /* Redesigned (2007) X10 1-way Lamp Module */
263 {"PLM03", MXLS, VNON, STDLM, 0, NULL, NULL }, /* Standard X10 1-way Lamp Module */
264 {"PLM01", MXLS, VNON, STDLM, 0, NULL, NULL }, /* Standard X10 1-way Lamp Module */
265 {"StdWS", MXLS, VNON, STDWS, 0, NULL, NULL }, /* Standard X10 1-way Lamp Wall Switch */
266 {"WS", MXLS, VNON, STDWS, 0, NULL, NULL }, /* Standard X10 1-way Lamp Wall Switch */
267 {"WS467", MXLS, VNON, STDWS, 0, NULL, NULL }, /* Standard X10 1-way Lamp Wall Switch */
268 {"LW10U", MXLS, VNON, STDWS, 0, NULL, NULL }, /* Marmitek Standard X10 1-way Lamp Wall Switch */
269 {"PLW01", MXLS, VNON, STDWS, 0, NULL, NULL }, /* Standard X10 1-way Lamp Wall Switch */
270 {"WS477", MXLS, VNON, STDWS, 0, NULL, NULL }, /* Standard X10 3-way Lamp Wall Switch */
271 {"PLW02", MXLS, VNON, STDWS, 0, NULL, NULL }, /* Standard X10 1-way Lamp Wall Switch */
272 {"WS467-1", MXLE, VNON, WS_1, XWS_1, NULL, NULL }, /* Redesigned (2007) X10 1-way Lamp Wall Switch */
273 {"WS-1", MXLE, VNON, WS_1, XWS_1, NULL, NULL }, /* Redesigned (2007) X10 1-way Lamp Wall Switch */
274 {"WS12A", MXLS, VNON, XPD3, 0, NULL, NULL }, /* X10 1-way Lamp Wall Switch */
275 {"XPD3", MXLS, VNON, XPD3, 0, NULL, NULL }, /* X10 Pro 1-way Lamp Wall Switch */
276 {"WS13A", MXLS, VNON, XPS3, 0, NULL, NULL }, /* X10 1-way non-dimming Wall Switch */
277 {"XPS3", MXLS, VNON, XPS3, 0, NULL, NULL }, /* X10 Pro 1-way non-dimming Wall Switch */
278 {"LM15A", MXLS, VNON, LM15A, 0, NULL, NULL }, /* X10 LM15A Socket Rocket */
279 {"LM15", MXLS, VNON, LM15A, 0, NULL, NULL }, /* Marmitek Socket Rocket */
280 {"PSM04", MXLS, VNON, LM15A, 0, NULL, NULL }, /* X10 Pro Socket Rocket */
281 {"LMS", MXLS, VNON, LMS, 0, NULL, NULL }, /* 2-way Lamp Module */
282 {"PR511", MXLS, VNON, PR511, 0, NULL, NULL }, /* X10 2-way Motion Sensor floodlight */
283 {"PHS01", MXLS, VNON, PR511, 0, NULL, NULL }, /* X10 Pro 2-way Motion Sensor floodlight */
284 {"AM14A", MXLEA, VNON, AM14A, XAM14A, NULL, NULL }, /* X10 2-way Appliance Module, 2-pin (AM14A) */
285 {"PAM21", MXLEA, VNON, AM14A, XAM14A, NULL, NULL }, /* X10 2-way Appliance Module, 2-pin (AM14A) */
286 {"AM15A", MXLEA, VNON, AM14A, XAM14A, NULL, NULL }, /* X10 2-way Appliance Module, 3-pin (AM15A) */
287 {"PAM22", MXLEA, VNON, AM14A, XAM14A, NULL, NULL }, /* X10 2-way Appliance Module, 3-pin (AM15A) */
288 {"LM14A", MXLE, VNON, LM14A, XLM14A, NULL, NULL }, /* X10 2-way Lamp Module (LM14A) */
289 {"PLM21", MXLE, VNON, LM14A, XLM14A, NULL, NULL }, /* X10 2-way Lamp Module (LM14A) */
290 {"SL1AM", MXLP, VNON, SL1AM, 0, NULL, NULL }, /* SwitchLinc 1-way Switch */
291 {"SL2AM", MXLP, VNON, SL2AM, 0, NULL, NULL }, /* SwitchLinc 2-way Switch */
292 {"SL1LM", MXLP, VNON, SL1LM, 0, opt_onlevel, NULL }, /* SwitchLinc 1-way Lamp Module */
293 {"SL2LM", MXLP, VNON, SL2LM, 0, opt_onlevel, NULL }, /* SwitchLinc 2-way Lamp Module */
294 {"SL2380W", MXLP, VNON, SL2LM, 0, opt_onlevel, NULL }, /* SwitchLinc 2380W Dimmer */
295 {"LL1LM", MXLP, VNON, LL1LM, 0, opt_onlevel, NULL }, /* LampLinc 1-way Dimmer */
296 {"LL2LM", MXLP, VNON, LL2LM, 0, opt_onlevel, NULL }, /* LampLink 2-way Dimmer */
297 {"LL2000STW", MXLP, VNON, LL2LM, 0, opt_onlevel, NULL }, /* LampLinc 2000STW Dimmer */
298 {"REMOTE2", MXLS, VNON, REM2, 0, NULL, NULL }, /* Remote transmitter, 2 function */
299 {"REMOTE3", MXLS, VNON, REM3, 0, NULL, NULL }, /* Remote transmitter, 3 function */
300 {"REMOTE4", MXLS, VNON, REM4, 0, NULL, NULL }, /* Remote transmitter, 4 function */
301 {"REMOTE6", MXLS, VNON, REM6, 0, NULL, NULL }, /* Remote transmitter, 6 function */
302 {"REMOTEP", MXLP, VNON, PRESET, 0, NULL, NULL }, /* Remote transmitter, Preset 1-32 only */
303 {"AMEXC", MXLS, VNON, AMEXC16, 0, NULL, NULL }, /* AM with exclusive-16 addressing */
304 {"AMEXC16", MXLS, VNON, AMEXC16, 0, NULL, NULL }, /* AM with exclusive addressing */
305 {"AMEXC8", MXLS, VNON, AMEXC8, 0, NULL, NULL }, /* AM with exclusive-8 addressing */
306 {"RAIN8", MXLS, VNON, AMEXC8, 0, NULL, NULL }, /* WGL Rain8 irrigation controller */
307 {"AMEXC4", MXLS, VNON, AMEXC4, 0, NULL, NULL }, /* AM with exclusive-4 addressing */
308 {"XM10A", MXLS, VNON, CAMEXC4, 0, NULL, NULL }, /* X10 camera power supply */
309 {"XM13A", MXLS, VNON, CAMEXC4, 0, NULL, NULL }, /* X10 camera power supply */
310 {"XM14A", MXLS, VNON, CAMEXC4, 0, NULL, NULL }, /* X10 pan/tilt power supply */
311 {"VIRT4", MXLV, VSTD, VIRT4, 0, opt_onlevel, NULL }, /* Virtual module, 4 function */
312 {"VDATA", MXLV, VSTD, VIRTUAL, 0, NULL, NULL }, /* Virtual module data */
313 {"PLCSENSOR", MXLS, VSTD, PLCSEN, 0, opt_plcsensor, NULL }, /* PLC Sensor target */
314 #ifdef HASEXT0
315 {"SHUTTER", MXLS0, VNON, SHUT0, XSHUT0, NULL, NULL }, /* Extended code Type 0 shutter */
316 {"SW10", MXLS0, VNON, SHUT0, XSHUT0, NULL, NULL }, /* Marmitek SW10 shutter control */
317 #endif
318
319 {"DS10A", MXLV, VSEC, VIRTUAL, 0, opt_sensor, fn_ds10a }, /* X-10 USA D/W sensor */
320 {"DS10", MXLV, VSEC, VIRTUAL, 0, opt_sensor, fn_ds10a }, /* Marmitek D/W sensor */
321 {"DS10E", MXLV, VSEC, VIRTUAL, 0, opt_sensor, fn_ds10a }, /* Marmitek D/W sensor */
322 {"PDS01", MXLV, VSEC, VIRTUAL, 0, opt_sensor, fn_ds10a }, /* X10 Pro D/W sensor */
323 {"DS18", MXLV, VSEC, VIRTUAL, 0, opt_sensor, fn_ds18 }, /* ElekHomica D/W sensor, old? */
324 {"DS90", MXLV, VSEC, VIRTUAL, 0, opt_ds90, fn_ds90 }, /* Marmitek D/W sensor */
325 {"DS18-1", MXLV, VSEC, VIRTUAL, 0, opt_ds90, fn_ds90 }, /* ElekHomica D/W sensor */
326
327 {"MS10A", MXLV, VSEC, VIRTUAL, 0, opt_sensor, fn_ms10a },
328 {"MS90", MXLV, VSEC, VIRTUAL, 0, opt_sensor, fn_ms90 }, /* Marmitek Motion sensor */
329 {"MS18E", MXLV, VSEC, VIRTUAL, 0, opt_sensor, fn_ms90 }, /* BMB Home Solutions Motion sensor */
330 {"SD10", MXLV, VSEC, VIRTUAL, 0, opt_sd10, fn_sd10 },
331 {"BMB-SD18", MXLV, VSEC, VIRTUAL, 0, opt_bmb_sd18, fn_bmb_sd18}, /* BMB Smoke Detector */
332 {"EH-CWSD10", MXLV, VSEC, VIRTUAL, 0, opt_sd10, fn_sd10 }, /* ElekHomica Smoke detector */
333 {"EH-WD210", MXLV, VSEC, VIRTUAL, 0, opt_sd10, fn_sd10 }, /* ElekHomica Water detector */
334 {"GB10", MXLV, VSEC, VIRTUAL, 0, opt_gb10, fn_gb10 }, /* Marmitek Glass Break detector */
335 {"DM10", MXLV, VSEC, VIRTUAL, 0, opt_gb10, fn_dm10 }, /* Marmitek DM10 Motion/Dawn/Dusk sensor */
336 {"SD90", MXLV, VSEC, VIRTUAL, 0, opt_sd90, fn_sd90 }, /* Marmitek Smoke detector */
337 {"PMS01", MXLV, VSEC, VIRTUAL, 0, opt_sensor, fn_ms10a },
338 {"SH624", MXLV, VSEC, VIRTUAL, 0, opt_sremote, fn_sh624 }, /* Full size remotes */
339 {"PSR01", MXLV, VSEC, VIRTUAL, 0, opt_sremote, fn_sh624 },
340 {"KR18", MXLV, VSEC, VIRTUAL, 0, opt_kremote, fn_kr18 }, /* Keyfob remotes */
341 {"KR18E", MXLV, VSEC, VIRTUAL, 0, opt_kremote, fn_kr18 },
342 {"KR10A", MXLV, VSEC, VIRTUAL, 0, opt_kremote, fn_kr10a },
343 {"KR21", MXLV, VSEC, VIRTUAL, 0, opt_kremote, fn_kr10a },
344 {"PKR02", MXLV, VSEC, VIRTUAL, 0, opt_kremote, fn_kr10a },
345 {"KR15A", MXLV, VSEC, VIRTUAL, 0, opt_sremote, fn_kr15a }, /* Big Red Button */
346 {"SVDATA", MXLV, VSEC, VIRTUAL, 0, opt_sremote, fn_svdata }, /* Generic security remote */
347 {"SSVDATA", MXLV, VSEC, VIRTUAL, 0, opt_svsensor, fn_svdata }, /* Generic security sensor */
348 {"SEC_IGNORE", MXLV, VSEC, VIRTUAL, 0, opt_secignore, NULL },
349 {"UR81A", MXLV, VENT, VIRTUAL, 0, opt_ur81a, fn_ur81a },
350 {"UR51A", MXLV, VENT, VIRTUAL, 0, opt_ur81a, fn_ur81a },
351 {"UX17A", MXLV, VENT, VIRTUAL, 0, opt_ux17a, NULL },
352 {"UX23A", MXLV, VENT, VIRTUAL, 0, opt_ux17a, NULL },
353 {"GURU", MXLV, VENT, VIRTUAL, 0, opt_guru, fn_guru },
354 {"PALMPAD", MXLS, VSTD, PALMPAD, 0, opt_aux, NULL},
355 {"KR19A", MXLS, VSTD, PALMPAD, 0, opt_aux, NULL},
356 {"KR22", MXLS, VSTD, PALMPAD, 0, opt_aux, NULL},
357 {"KEYCHAIN", MXLS, VSTD, KEYCHAIN, 0, opt_aux, NULL},
358 {"ONLYON", MXLS, VSTD, ONLYON, 0, opt_aux, NULL},
359 {"ONLYOFF", MXLS, VSTD, ONLYOFF, 0, opt_aux, NULL},
360 {"MS12", MXLS, VSTD, MOTION, 0, opt_x10std, NULL},
361 {"MS12A", MXLS, VSTD, MOTION, 0, opt_x10std, NULL},
362 {"MS13", MXLS, VSTD, MOTION, 0, opt_x10std, NULL},
363 {"MS13A", MXLS, VSTD, MOTION, 0, opt_x10std, NULL},
364 {"MS14", MXLS, VSTD, MOTION, 0, opt_x10std, NULL},
365 {"MS14A", MXLS, VSTD, MOTION, 0, opt_x10std, NULL},
366 {"MS16", MXLS, VSTD, MOTION, 0, opt_x10std, NULL},
367 {"MS16A", MXLS, VSTD, MOTION, 0, opt_x10std, NULL},
368
369 #ifdef HASORE
370 {"ORE_TH1", MXLV, VORE, VIRTUAL, 0, opt_oreTH1, NULL},
371 {"THGR122NX", MXLV, VORE, VIRTUAL, 0, opt_oreTH1, NULL},
372 {"THGN123N", MXLV, VORE, VIRTUAL, 0, opt_oreTH1, NULL},
373 {"THGR228N", MXLV, VORE, VIRTUAL, 0, opt_oreTH1, NULL},
374 {"ORE_TH2", MXLV, VORE, VIRTUAL, 0, opt_oreTH2, NULL},
375 {"THGN800", MXLV, VORE, VIRTUAL, 0, opt_oreTH2, NULL},
376 {"THGR800", MXLV, VORE, VIRTUAL, 0, opt_oreTH2, NULL},
377 {"THGR810", MXLV, VORE, VIRTUAL, 0, opt_oreTH2, NULL},
378 {"ORE_TH3", MXLV, VORE, VIRTUAL, 0, opt_oreTH3, NULL},
379 {"RTGN318", MXLV, VORE, VIRTUAL, 0, opt_oreTH3, NULL},
380 {"RTGR328N", MXLV, VORE, VIRTUAL, 0, opt_oreTH3, NULL},
381 {"ORE_TH4", MXLV, VORE, VIRTUAL, 0, opt_oreTH4, NULL},
382 {"ORE_TH5", MXLV, VORE, VIRTUAL, 0, opt_oreTH5, NULL},
383 {"ORE_TH6", MXLV, VORE, VIRTUAL, 0, opt_oreTH6, NULL},
384 {"THGR918N", MXLV, VORE, VIRTUAL, 0, opt_oreTH6, NULL},
385 {"ORE_T1", MXLV, VORE, VIRTUAL, 0, opt_oreTemp1, NULL},
386 {"THR138", MXLV, VORE, VIRTUAL, 0, opt_oreTemp1, NULL},
387 {"ORE_T2", MXLV, VORE, VIRTUAL, 0, opt_oreTemp2, NULL},
388 {"THRN122N", MXLV, VORE, VIRTUAL, 0, opt_oreTemp2, NULL},
389 {"THN122N", MXLV, VORE, VIRTUAL, 0, opt_oreTemp2, NULL},
390 {"THN132N", MXLV, VORE, VIRTUAL, 0, opt_oreTemp2, NULL},
391 {"ORE_T3", MXLV, VORE, VIRTUAL, 0, opt_oreTemp3, NULL},
392 {"ORE_THB1", MXLV, VORE, VIRTUAL, 0, opt_oreTHB1, NULL},
393 {"BTHR918", MXLV, VORE, VIRTUAL, 0, opt_oreTHB1, NULL},
394 {"ORE_THB2", MXLV, VORE, VIRTUAL, 0, opt_oreTHB2, NULL},
395 {"BTHR968", MXLV, VORE, VIRTUAL, 0, opt_oreTHB2, NULL},
396 {"BTHR918N", MXLV, VORE, VIRTUAL, 0, opt_oreTHB2, NULL},
397 {"ORE_WGT1", MXLV, VORE, VIRTUAL, 0, opt_oreWeight1, NULL},
398 {"BWR102", MXLV, VORE, VIRTUAL, 0, opt_oreWeight1, NULL},
399 {"ORE_TEMU", MXLV, VORE, VIRTUAL, 0, opt_oreTemu, NULL}, /* Dummy */
400 {"ORE_THEMU", MXLV, VORE, VIRTUAL, 0, opt_oreTHemu, NULL}, /* Dummy */
401 {"ORE_THBEMU", MXLV, VORE, VIRTUAL, 0, opt_oreTHBemu, NULL}, /* Dummy */
402 {"ORE_IGNORE", MXLV, VORE, VIRTUAL, 0, opt_oreignore, NULL},
403 {"ORE_WIND1", MXLV, VORE, VIRTUAL, 0, opt_oreWind1, NULL},
404 {"ORE_WIND2", MXLV, VORE, VIRTUAL, 0, opt_oreWind2, NULL},
405 {"WGR800", MXLV, VORE, VIRTUAL, 0, opt_oreWind2, NULL},
406 {"ORE_WIND3", MXLV, VORE, VIRTUAL, 0, opt_oreWind3, NULL},
407 {"WGR918N", MXLV, VORE, VIRTUAL, 0, opt_oreWind3, NULL},
408 {"ORE_RAIN1", MXLV, VORE, VIRTUAL, 0, opt_oreRain1, NULL},
409 {"PCR918N", MXLV, VORE, VIRTUAL, 0, opt_oreRain1, NULL},
410 {"ORE_RAIN2", MXLV, VORE, VIRTUAL, 0, opt_oreRain2, NULL},
411 {"PCR800", MXLV, VORE, VIRTUAL, 0, opt_oreRain2, NULL},
412 {"ORE_RAIN3", MXLV, VORE, VIRTUAL, 0, opt_oreRain3, NULL},
413 {"ELS_CM113", MXLV, VORE, VIRTUAL, 0, opt_elsElec1, NULL},
414 {"ELS_ELEC1", MXLV, VORE, VIRTUAL, 0, opt_elsElec1, NULL},
415 {"ORE_ELS", MXLV, VORE, VIRTUAL, 0, opt_elsElec1, NULL},
416 {"ORE_UV1", MXLV, VORE, VIRTUAL, 0, opt_oreUV1, NULL},
417 {"ORE_UV2", MXLV, VORE, VIRTUAL, 0, opt_oreUV2, NULL},
418 {"OWL_ELEC2", MXLV, VORE, VIRTUAL, 0, opt_owlElec2new, NULL},
419 #endif /* HASORE */
420
421 #ifdef HASRFXS
422 {"RFXSENSOR", MXLV, VRFXS, VIRTUAL, 0, opt_rfxsensor, fn_rfxsensor},
423 #endif /* HASRFXS */
424
425 #ifdef HASRFXM
426 {"RFXCOUNT", MXLV, VRFXM, VIRTUAL, 0, opt_rfxcount, fn_rfxcount},
427 {"RFXPOWER", MXLV, VRFXM, VIRTUAL, 0, opt_rfxpower, fn_rfxpower},
428 {"RFXWATER", MXLV, VRFXM, VIRTUAL, 0, opt_rfxwater, fn_rfxwater},
429 {"RFXGAS", MXLV, VRFXM, VIRTUAL, 0, opt_rfxgas, fn_rfxgas},
430 {"RFXPULSE", MXLV, VRFXM, VIRTUAL, 0, opt_rfxpulse, fn_rfxpulse},
431 #endif /* HASRFXM */
432
433 #ifdef HASDMX
434 {"DIGIMAX", MXLV, VDMX, VIRTUAL, 0, opt_digimax, NULL},
435 #endif /* HASDMX */
436
437 #ifdef HASKAKU
438 {"KAKU_S", MXLK, VKAKU, KAM, 0, opt_kaku, NULL},
439 {"KAKU_P", MXLK, VKAKU, KLM, 0, opt_kaku, NULL},
440 #endif /* HASKAKU */
441
442 {"VISGEN", MXLV, VSEC, VIRTUAL, 0, opt_visonic, fn_visonic }, /* Generic Visonic */
443
444 };
445 static int ntypes = (sizeof(modules)/sizeof(struct modules_st));
446
447 unsigned int modmask[NumModMasks][16];
448 unsigned int vmodmask[NumVmodMasks][16];
449 unsigned int kmodmask[NumKmodMasks][16];
450 unsigned char maxdimlevel[16][16];
451 unsigned char ondimlevel[16][16];
452
453 extern CONFIG config;
454 extern CONFIG *configp;
455
456
457 /*-------------------------------------------------------+
458 | Return a pointer to a module xlate_func() |
459 +-------------------------------------------------------*/
module_xlate_func(int index)460 int (*module_xlate_func(int index))()
461 {
462 return modules[index].xlate_func;
463 }
464
465 /*-------------------------------------------------------+
466 | Return the index in the module table for the argument |
467 | name, or -1 if not found |
468 | The comparison is case insensitive |
469 +-------------------------------------------------------*/
lookup_module_type(char * modelname)470 int lookup_module_type ( char *modelname )
471 {
472 char buffer[NAME_LEN + 1], label[NAME_LEN + 1];
473 int j;
474
475 strncpy2(buffer, modelname, sizeof(buffer) - 1);
476 strupper(buffer);
477
478 for ( j = 0; j < ntypes; j++ ) {
479 strncpy2(label, modules[j].label, sizeof(label) - 1);
480 strupper(label);
481 if ( strcmp(buffer, label) == 0 )
482 return j;
483 }
484
485 return -1;
486 }
487
488 /*-------------------------------------------------------+
489 | Pass back through the argument list the flags and |
490 | maxlevel values for module index 'module_type' |
491 +-------------------------------------------------------*/
module_attributes(int module_type,unsigned long * vflags,unsigned long * cflags,unsigned long * xflags,unsigned long * kflags,int * maxlevel)492 void module_attributes ( int module_type,
493 unsigned long *vflags, unsigned long *cflags,
494 unsigned long *xflags, unsigned long *kflags, int *maxlevel )
495 {
496 if ( module_type >= 0 ) {
497 *vflags = modules[module_type].vflags;
498 *cflags = modules[module_type].cflags;
499 if ( *vflags & VKAKU ) {
500 *kflags = *cflags;
501 *cflags = 0;
502 }
503 else {
504 *kflags = 0;
505 }
506 *xflags = modules[module_type].xflags;
507 *maxlevel = modules[module_type].maxlevel;
508 }
509 else {
510 *vflags = 0;
511 *cflags = 0;
512 *xflags = 0;
513 *kflags = 0;
514 *maxlevel = 0;
515 }
516 return;
517 }
518
519 /*-------------------------------------------------------+
520 | Called by add_alias() to add options specified on the |
521 | ALIAS line in the config file. |
522 +-------------------------------------------------------*/
add_module_options(ALIAS * aliasp,int aliasindex,char ** tokens,int ntokens)523 int add_module_options ( ALIAS *aliasp, int aliasindex,
524 char **tokens, int ntokens )
525 {
526 int type;
527
528 type = aliasp[aliasindex].modtype;
529
530 if ( modules[type].addopt_func == NULL ) {
531 if ( ntokens > 0 ) {
532 store_error_message("No parameters are supported for this module type.");
533 return 1;
534 }
535 return 0;
536 }
537
538 return modules[type].addopt_func(aliasp, aliasindex, tokens, &ntokens);
539 }
540
541
542 /*-------------------------------------------------------+
543 | Display options specified for an ALIAS. |
544 +-------------------------------------------------------*/
display_module_options(int aliasindex)545 char *display_module_options (int aliasindex )
546 {
547 static char buffer[128];
548 ALIAS *aliasp;
549 long int optflags, optflags2;
550 int j, k;
551 int rh;
552 double tempc, bp;
553 char keystr[4], grpstr[4];
554 long secs;
555
556 aliasp = configp->aliasp;
557
558 if ( !aliasp )
559 return "";
560
561
562 optflags = aliasp[aliasindex].optflags;
563 optflags2 = aliasp[aliasindex].optflags2;
564
565 buffer[0] = '\0';
566
567 if ( optflags & MOPT_RESUME )
568 sprintf(buffer, "ONLEVEL RESUME");
569 else if ( optflags & MOPT_ONFULL && aliasp[aliasindex].flags & PRESET)
570 sprintf(buffer, "ONLEVEL %d", aliasp[aliasindex].onlevel + 1);
571 else if ( optflags & MOPT_ONFULL )
572 sprintf(buffer, "ONLEVEL %d", aliasp[aliasindex].onlevel);
573
574 if ( optflags & MOPT_SECURITY || optflags & MOPT_ENTERTAIN ) {
575 buffer[0] = '\0';
576 for ( j = 0; j < aliasp[aliasindex].nident; j++ )
577 sprintf(buffer + strlen(buffer), "0x%02lx ", aliasp[aliasindex].ident[j]);
578 }
579
580 if ( optflags & MOPT_MAIN ) strcat(buffer, "MAIN ");
581 if ( optflags & MOPT_AUX ) strcat(buffer, "AUX ");
582
583 if ( optflags & MOPT_TRANSCEIVE ) strcat(buffer, "TRANSCEIVE ");
584 if ( optflags & MOPT_RFFORWARD ) strcat(buffer, "RFFORWARD ");
585 if ( optflags & MOPT_RFIGNORE ) strcat(buffer, "RFIGNORE ");
586 if ( optflags & MOPT_REVERSE ) strcat(buffer, "REVERSE ");
587
588 if ( optflags2 & MOPT2_DUMMY ) strcat(buffer, "DUMMY ");
589
590 if ( optflags & MOPT_RFXSENSOR ) {
591 sprintf(buffer + strlen(buffer), "0x%02lx ", aliasp[aliasindex].ident[0]);
592 strcat(buffer, "T");
593 if ( optflags & MOPT_RFXRH ) strcat(buffer, "H ");
594 else if ( optflags & MOPT_RFXBP ) strcat(buffer, "B ");
595 else if ( optflags & MOPT_RFXVAD ) strcat(buffer, "V ");
596 else if ( optflags & MOPT_RFXPOT ) strcat(buffer, "P ");
597 else if ( optflags & MOPT_RFXT2 ) strcat(buffer, "T ");
598 else strcat(buffer, " ");
599 }
600
601 if ( optflags & MOPT_RFXMETER ) {
602 sprintf(buffer + strlen(buffer), "0x%02lx ", aliasp[aliasindex].ident[0]);
603 }
604
605 if ( optflags & MOPT_KAKU ) {
606 for ( j = 0; j < aliasp[aliasindex].nident; j++ ) {
607 *keystr = '\0';
608 for ( k = 0; k < 16; k++ ) {
609 if ( aliasp[aliasindex].kaku_keymap[j] & (1 << k) ) {
610 sprintf(keystr, "%d", k + 1);
611 break;
612 }
613 }
614 *grpstr = '\0';
615 for ( k = 0; k < 16; k++ ) {
616 if ( aliasp[aliasindex].kaku_grpmap[j] & (1 << k) ) {
617 sprintf(grpstr, "%c", k + 'A');
618 break;
619 }
620 }
621
622 sprintf(buffer + strlen(buffer), "0x%07lx %s%s ",
623 aliasp[aliasindex].ident[j], keystr, grpstr);
624 }
625 }
626
627 if ( optflags2 & MOPT2_TMIN ) {
628 tempc = (double)aliasp[aliasindex].tmin / 10.0;
629 sprintf(buffer + strlen(buffer), "TMIN "FMT_ORET"%c ",
630 celsius2temp(tempc, configp->ore_tscale, 0.0), configp->ore_tscale );
631 }
632 if ( optflags2 & MOPT2_TMAX ) {
633 tempc = (double)aliasp[aliasindex].tmax / 10.0;
634 sprintf(buffer + strlen(buffer), "TMAX "FMT_ORET"%c ",
635 celsius2temp(tempc, configp->ore_tscale, 0.0), configp->ore_tscale );
636 }
637 if ( optflags2 & MOPT2_RHMIN ) {
638 rh = aliasp[aliasindex].rhmin;
639 sprintf(buffer + strlen(buffer), "RHMIN %d%% ", rh);
640 }
641 if ( optflags2 & MOPT2_RHMAX ) {
642 rh = aliasp[aliasindex].rhmax;
643 sprintf(buffer + strlen(buffer), "RHMAX %d%% ", rh);
644 }
645 if ( optflags2 & MOPT2_BPMIN ) {
646 bp = (double)aliasp[aliasindex].bpmin;
647 sprintf(buffer + strlen(buffer), "BPMIN "FMT_OREBP"%s ",
648 (bp * configp->ore_bpscale) + configp->ore_bpoffset, configp->ore_bpunits );
649 }
650 if ( optflags2 & MOPT2_BPMAX ) {
651 bp = (double)aliasp[aliasindex].bpmax;
652 sprintf(buffer + strlen(buffer), "BPMAX "FMT_OREBP"%s ",
653 (bp * configp->ore_bpscale) + configp->ore_bpoffset, configp->ore_bpunits );
654 }
655
656 if ( optflags2 & MOPT2_SWHOME ) {
657 strcat(buffer + strlen(buffer), "SWHOME ");
658 }
659 if ( optflags2 & MOPT2_SWMAX ) {
660 strcat(buffer + strlen(buffer), "SWMAX ");
661 }
662 if ( optflags2 & MOPT2_DUMMY ) {
663 strcat(buffer + strlen(buffer), "DUMMY ");
664 }
665
666 /* Inactive timeout */
667 if ( optflags2 & MOPT2_IATO ) {
668 secs = aliasp[aliasindex].hb_timeout;
669 sprintf(buffer + strlen(buffer), "IATO %ld:%02ld:%02ld ", (secs / 3600L), (secs % 3600L) / 60L, (secs % 60));
670 }
671
672 /* ACT module options */
673 if ( optflags2 & MOPT2_AUF ) {
674 sprintf(buffer + strlen(buffer), "AUF ");
675 }
676 if ( optflags2 & MOPT2_ALO ) {
677 sprintf(buffer + strlen(buffer), "ALO ");
678 }
679 if ( optflags2 & MOPT2_ALF ) {
680 sprintf(buffer + strlen(buffer), "ALF ");
681 }
682
683 /* Defer update for 2-way modules with auto status response */
684 if ( optflags2 & MOPT2_DEFER ) {
685 sprintf(buffer + strlen(buffer), "DEFER ");
686 }
687
688 return buffer;
689 }
690
691
692 /*-------------------------------------------------------+
693 | Return a pointer to the module name corresponding to |
694 | the argument module_type. |
695 +-------------------------------------------------------*/
lookup_module_name(int module_type)696 char *lookup_module_name ( int module_type )
697 {
698
699 if ( module_type >= 0 && module_type < ntypes )
700 return modules[module_type].label;
701
702 return "";
703 }
704
705 /*-------------------------------------------------------+
706 | Create the state filter determined by characteristics |
707 | of each module defined in the config file. |
708 +-------------------------------------------------------*/
set_module_masks(ALIAS * aliasp)709 void set_module_masks ( ALIAS *aliasp )
710 {
711 int j, ucode;
712 unsigned char hcode, maxlevel, onlevel;
713 unsigned int bitmap, vflags, cflags, xflags, kflags;
714 unsigned int defined[16];
715
716 if ( configp->module_types == NO ) {
717 for ( j = 0; j < NumModMasks; j++ ) {
718 for ( hcode = 0; hcode < 16; hcode++ )
719 modmask[j][hcode] = 0xffff;
720 }
721 return;
722 }
723
724 /* Default for undefined modules */
725 vflags = modules[configp->default_module].vflags;
726 cflags = modules[configp->default_module].cflags;
727 if ( vflags & VKAKU ) {
728 kflags = cflags;
729 cflags = 0;
730 }
731 else {
732 kflags = 0;
733 }
734 xflags = modules[configp->default_module].xflags;
735 maxlevel = modules[configp->default_module].maxlevel;
736
737 /* Record housecode|units with defined module type */
738 for ( j = 0; j < 16; j++ ) {
739 defined[j] = 0;
740 }
741 j = 0;
742 while ( aliasp && aliasp[j].line_no > 0 ) {
743 if ( aliasp[j].modtype >= 0 ) {
744 /* Module is defined */
745 hcode = hc2code(aliasp[j].housecode);
746 defined[hcode] |= aliasp[j].unitbmap;
747 }
748 j++;
749 }
750
751 /* Initialize to zero */
752 for ( j = 0; j < NumModMasks; j++ ) {
753 for ( hcode = 0; hcode < 16; hcode++ )
754 modmask[j][hcode] = 0;
755 }
756 for ( j = 0; j < NumVmodMasks; j++ ) {
757 for ( hcode = 0; hcode < 16; hcode++ )
758 vmodmask[j][hcode] = 0;
759 }
760 for ( j = 0; j < NumKmodMasks; j++ ) {
761 for ( hcode = 0; hcode < 16; hcode++ )
762 kmodmask[j][hcode] = 0;
763 }
764
765 /* Set the characteristic of undefined modules */
766 for ( hcode = 0; hcode < 16; hcode++ ) {
767 bitmap = ~defined[hcode];
768
769 /* Mark units which respond */
770 if ( cflags & ADDRESSED )
771 modmask[AddrMask][hcode] = bitmap;
772 if ( cflags & PHYS )
773 modmask[PhysMask][hcode] = bitmap;
774 if ( cflags & UNOFF )
775 modmask[AllOffMask][hcode] = bitmap;
776 if ( cflags & LION )
777 modmask[LightsOnMask][hcode] = bitmap;
778 if ( cflags & MON )
779 modmask[OnMask][hcode] = bitmap;
780 if ( cflags & MOFF )
781 modmask[OffMask][hcode] = bitmap;
782 if ( cflags & DIM )
783 modmask[DimMask][hcode] = bitmap;
784 if ( cflags & BRI )
785 modmask[BriMask][hcode] = bitmap;
786 if ( cflags & LIOFF )
787 modmask[LightsOffMask][hcode] = bitmap;
788 if ( cflags & BRIB4DIM )
789 modmask[BriDimMask][hcode] = bitmap;
790 if ( cflags & STDX10 )
791 modmask[StdMask][hcode] = bitmap;
792 if ( cflags & PRESET )
793 modmask[PresetMask][hcode] = bitmap;
794 if ( cflags & STAREQ )
795 modmask[StatusMask][hcode] = bitmap;
796 if ( cflags & STAON )
797 modmask[StatusOnMask][hcode] = bitmap;
798 if ( cflags & STAOFF )
799 modmask[StatusOffMask][hcode] = bitmap;
800 if ( cflags & LIONFULL )
801 modmask[LightsOnFullMask][hcode] = bitmap;
802 if ( cflags & ONFULL )
803 modmask[OnFullMask][hcode] = bitmap;
804 if ( cflags & ONFULLOFF )
805 modmask[OnFullOffMask][hcode] = bitmap;
806 if ( cflags & ALLON )
807 modmask[AllOnMask][hcode] = bitmap;
808 if ( cflags & RESUME )
809 modmask[ResumeMask][hcode] = bitmap;
810 if ( cflags & TARG )
811 modmask[TargMask][hcode] = bitmap;
812 if ( cflags & EXC16 )
813 modmask[Exc16Mask][hcode] = bitmap;
814 if ( cflags & EXC8 )
815 modmask[Exc8Mask][hcode] = bitmap;
816 if ( cflags & EXC4 )
817 modmask[Exc4Mask][hcode] = bitmap;
818 if ( cflags & VDATA || vflags & VKAKU )
819 modmask[VdataMask][hcode] = bitmap;
820 if ( cflags & RESUMEDIM )
821 modmask[ResumeDimMask][hcode] = bitmap;
822 if ( cflags & LIONUNAD )
823 modmask[LightsOnUnaddrMask][hcode] = bitmap;
824 if ( cflags & LIOFFUNAD )
825 modmask[LightsOffUnaddrMask][hcode] = bitmap;
826 if ( cflags & PLCSENSOR )
827 modmask[PlcSensorMask][hcode] = bitmap;
828 if ( cflags & ONOFFUNAD )
829 modmask[OnOffUnaddrMask][hcode] = bitmap;
830
831 if ( xflags & X0SH )
832 modmask[Ext0Mask][hcode] = bitmap;
833
834 if ( xflags & X3SW ) {
835 modmask[Ext3Mask][hcode] = bitmap;
836 modmask[AllOnMask][hcode] = bitmap;
837 }
838 if ( xflags & X3DIM )
839 modmask[Ext3DimMask][hcode] = bitmap;
840 if ( xflags & X3GEXEC )
841 modmask[Ext3GrpExecMask][hcode] = bitmap;
842 if ( xflags & X3GRC1 )
843 modmask[Ext3GrpRelT1Mask][hcode] = bitmap;
844 if ( xflags & X3GRC2 )
845 modmask[Ext3GrpRelT2Mask][hcode] = bitmap;
846 if ( xflags & X3GRC3 )
847 modmask[Ext3GrpRelT3Mask][hcode] = bitmap;
848 if ( xflags & X3GRC4 )
849 modmask[Ext3GrpRelT4Mask][hcode] = bitmap;
850 if ( xflags & X3GOFF )
851 modmask[Ext3GrpOffMask][hcode] = bitmap;
852 if ( xflags & X3GOFFEX )
853 modmask[Ext3GrpOffExecMask][hcode] = bitmap;
854 if ( xflags & X3GBD )
855 modmask[Ext3GrpBriDimMask][hcode] = bitmap;
856 if ( xflags & X3GBDFULL )
857 modmask[Ext3GrpBriDimFullMask][hcode] = bitmap;
858 if ( xflags & X3STAT )
859 modmask[Ext3StatusMask][hcode] = bitmap;
860 if ( xflags & X3GREM )
861 modmask[Ext3GrpRemMask][hcode] = bitmap;
862
863 if ( vflags & VSTD )
864 vmodmask[VstdMask][hcode] = bitmap;
865 if ( vflags & VENT )
866 vmodmask[VentMask][hcode] = bitmap;
867 if ( vflags & VSEC )
868 vmodmask[VsecMask][hcode] = bitmap;
869 if ( vflags & VRFXS )
870 vmodmask[VrfxsMask][hcode] = bitmap;
871 if ( vflags & VRFXM )
872 vmodmask[VrfxmMask][hcode] = bitmap;
873 if ( vflags & VDMX )
874 vmodmask[VdmxMask][hcode] = bitmap;
875 if ( vflags & VORE )
876 vmodmask[VoreMask][hcode] = bitmap;
877 if ( vflags & VKAKU )
878 vmodmask[VkakuMask][hcode] = bitmap;
879
880 if ( kflags & KON )
881 kmodmask[KonMask][hcode] = bitmap;
882 if ( kflags & KOFF )
883 kmodmask[KoffMask][hcode] = bitmap;
884 if ( kflags & KGON )
885 kmodmask[KGonMask][hcode] = bitmap;
886 if ( kflags & KGOFF )
887 kmodmask[KGoffMask][hcode] = bitmap;
888 if ( kflags & KPRE )
889 kmodmask[KpreMask][hcode] = bitmap;
890 if ( kflags & KGPRE )
891 kmodmask[KGpreMask][hcode] = bitmap;
892 if ( kflags & KRESUME )
893 kmodmask[KresumeMask][hcode] = bitmap;
894 if ( kflags & KPHYS )
895 kmodmask[KPhysMask][hcode] = bitmap;
896
897 if ( !vflags || (vflags & VSTD) )
898 vmodmask[VtstampMask][hcode] = bitmap;
899
900 /* Set max and on dim levels for each unit */
901 for ( ucode = 0; ucode < 16; ucode++ ) {
902 if ( bitmap & (1 << ucode) ) {
903 maxdimlevel[hcode][ucode] = maxlevel;
904 ondimlevel[hcode][ucode] = maxlevel;
905 }
906 }
907 }
908
909 /* Now fill in the characteristics of defined modules */
910 j = 0;
911 while ( aliasp && aliasp[j].line_no > 0 ) {
912 if ( aliasp[j].modtype < 0 ) {
913 /* Module is undefined */
914 j++;
915 continue;
916 }
917 hcode = hc2code(aliasp[j].housecode);
918 bitmap = aliasp[j].unitbmap;
919 cflags = aliasp[j].flags;
920 vflags = aliasp[j].vflags;
921 xflags = aliasp[j].xflags;
922 kflags = aliasp[j].kflags;
923 maxlevel = aliasp[j].maxlevel;
924 onlevel = aliasp[j].onlevel;
925
926 /* Mark units which respond */
927 if ( cflags & ADDRESSED )
928 modmask[AddrMask][hcode] |= bitmap;
929 if ( cflags & PHYS )
930 modmask[PhysMask][hcode] |= bitmap;
931 if ( cflags & UNOFF )
932 modmask[AllOffMask][hcode] |= bitmap;
933 if ( cflags & LION )
934 modmask[LightsOnMask][hcode] |= bitmap;
935 if ( cflags & MON )
936 modmask[OnMask][hcode] |= bitmap;
937 if ( cflags & MOFF )
938 modmask[OffMask][hcode] |= bitmap;
939 if ( cflags & DIM )
940 modmask[DimMask][hcode] |= bitmap;
941 if ( cflags & BRI )
942 modmask[BriMask][hcode] |= bitmap;
943 if ( cflags & LIOFF )
944 modmask[LightsOffMask][hcode] |= bitmap;
945 if ( cflags & BRIB4DIM )
946 modmask[BriDimMask][hcode] |= bitmap;
947 if ( cflags & STDX10 )
948 modmask[StdMask][hcode] |= bitmap;
949 if ( cflags & PRESET )
950 modmask[PresetMask][hcode] |= bitmap;
951 if ( cflags & STAREQ )
952 modmask[StatusMask][hcode] |= bitmap;
953 if ( cflags & STAON )
954 modmask[StatusOnMask][hcode] |= bitmap;
955 if ( cflags & STAOFF )
956 modmask[StatusOffMask][hcode] |= bitmap;
957 if ( cflags & LIONFULL )
958 modmask[LightsOnFullMask][hcode] |= bitmap;
959 if ( cflags & ONFULL )
960 modmask[OnFullMask][hcode] |= bitmap;
961 if ( cflags & ONFULLOFF )
962 modmask[OnFullOffMask][hcode] |= bitmap;
963 if ( cflags & ALLON )
964 modmask[AllOnMask][hcode] |= bitmap;
965 if ( cflags & RESUME )
966 modmask[ResumeMask][hcode] |= bitmap;
967 if ( cflags & TARG )
968 modmask[TargMask][hcode] |= bitmap;
969 if ( cflags & EXC16 )
970 modmask[Exc16Mask][hcode] |= bitmap;
971 if ( cflags & EXC8 )
972 modmask[Exc8Mask][hcode] |= bitmap;
973 if ( cflags & EXC4 )
974 modmask[Exc4Mask][hcode] |= bitmap;
975 if ( cflags & VDATA || vflags & VKAKU )
976 modmask[VdataMask][hcode] |= bitmap;
977 if ( cflags & RESUMEDIM )
978 modmask[ResumeDimMask][hcode] |= bitmap;
979 if ( cflags & LIONUNAD )
980 modmask[LightsOnUnaddrMask][hcode] |= bitmap;
981 if ( cflags & LIOFFUNAD )
982 modmask[LightsOffUnaddrMask][hcode] |= bitmap;
983 if ( cflags & PLCSENSOR )
984 modmask[PlcSensorMask][hcode] |= bitmap;
985 if ( cflags & ONOFFUNAD )
986 modmask[OnOffUnaddrMask][hcode] |= bitmap;
987
988 if ( xflags & X0SH )
989 modmask[Ext0Mask][hcode] |= bitmap;
990
991 if ( xflags & X3SW ) {
992 modmask[Ext3Mask][hcode] |= bitmap;
993 modmask[AllOnMask][hcode] |= bitmap;
994 }
995 if ( xflags & X3DIM )
996 modmask[Ext3DimMask][hcode] |= bitmap;
997 if ( xflags & X3GEXEC )
998 modmask[Ext3GrpExecMask][hcode] |= bitmap;
999 if ( xflags & X3GRC1 )
1000 modmask[Ext3GrpRelT1Mask][hcode] |= bitmap;
1001 if ( xflags & X3GRC2 )
1002 modmask[Ext3GrpRelT2Mask][hcode] |= bitmap;
1003 if ( xflags & X3GRC3 )
1004 modmask[Ext3GrpRelT3Mask][hcode] |= bitmap;
1005 if ( xflags & X3GRC4 )
1006 modmask[Ext3GrpRelT4Mask][hcode] |= bitmap;
1007 if ( xflags & X3GOFF )
1008 modmask[Ext3GrpOffMask][hcode] |= bitmap;
1009 if ( xflags & X3GOFFEX )
1010 modmask[Ext3GrpOffExecMask][hcode] |= bitmap;
1011 if ( xflags & X3GBD )
1012 modmask[Ext3GrpBriDimMask][hcode] |= bitmap;
1013 if ( xflags & X3GBDFULL )
1014 modmask[Ext3GrpBriDimFullMask][hcode] |= bitmap;
1015 if ( xflags & X3STAT )
1016 modmask[Ext3StatusMask][hcode] |= bitmap;
1017 if ( xflags & X3GREM )
1018 modmask[Ext3GrpRemMask][hcode] |= bitmap;
1019
1020 if ( kflags & KON )
1021 kmodmask[KonMask][hcode] |= bitmap;
1022 if ( kflags & KOFF )
1023 kmodmask[KoffMask][hcode] |= bitmap;
1024 if ( kflags & KGON )
1025 kmodmask[KGonMask][hcode] |= bitmap;
1026 if ( kflags & KGOFF )
1027 kmodmask[KGoffMask][hcode] |= bitmap;
1028 if ( kflags & KPRE )
1029 kmodmask[KpreMask][hcode] |= bitmap;
1030 if ( kflags & KGPRE )
1031 kmodmask[KGpreMask][hcode] |= bitmap;
1032 if ( kflags & KRESUME )
1033 kmodmask[KresumeMask][hcode] |= bitmap;
1034 if ( kflags & KPHYS )
1035 kmodmask[KPhysMask][hcode] |= bitmap;
1036
1037 if ( vflags & VSTD )
1038 vmodmask[VstdMask][hcode] |= bitmap;
1039 if ( vflags & VENT )
1040 vmodmask[VentMask][hcode] |= bitmap;
1041 if ( vflags & VSEC )
1042 vmodmask[VsecMask][hcode] |= bitmap;
1043 if ( vflags & VRFXS )
1044 vmodmask[VrfxsMask][hcode] |= bitmap;
1045 if ( vflags & VRFXM )
1046 vmodmask[VrfxmMask][hcode] |= bitmap;
1047 if ( vflags & VDMX )
1048 vmodmask[VdmxMask][hcode] |= bitmap;
1049 if ( vflags & VORE )
1050 vmodmask[VoreMask][hcode] |= bitmap;
1051 if ( vflags & VKAKU )
1052 vmodmask[VkakuMask][hcode] |= bitmap;
1053 if ( !vflags || (vflags & VSTD) )
1054 vmodmask[VtstampMask][hcode] |= bitmap;
1055
1056 /* ACT module options */
1057 if ( aliasp[j].optflags2 & MOPT2_AUF )
1058 modmask[AllOffMask][hcode] |= bitmap;
1059 if ( aliasp[j].optflags2 & MOPT2_ALO ) {
1060 modmask[LightsOnMask][hcode] |= bitmap;
1061 modmask[OnFullMask][hcode] |= bitmap;
1062 }
1063 if ( aliasp[j].optflags2 & MOPT2_ALF )
1064 modmask[LightsOffMask][hcode] |= bitmap;
1065
1066 if ( aliasp[j].optflags2 & MOPT2_DEFER )
1067 modmask[DeferMask][hcode] |= bitmap;
1068
1069
1070 /* Set max and on dim levels for each unit */
1071 for ( ucode = 0; ucode < 16; ucode++ ) {
1072 if ( bitmap & (1 << ucode) ) {
1073 maxdimlevel[hcode][ucode] = maxlevel;
1074 ondimlevel[hcode][ucode] = onlevel;
1075 }
1076 }
1077
1078 j++;
1079 }
1080
1081 return;
1082 }
1083
1084
1085 /*-------------------------------------------------------+
1086 | Display a table indicating the module attributes |
1087 | (either defined or defaults) for each unit |
1088 +-------------------------------------------------------*/
show_module_mask(unsigned char hcode)1089 void show_module_mask ( unsigned char hcode )
1090 {
1091 char hc, *chr = ".*x", *chr2 = ".*?";
1092 int j, lw = 13;
1093 unsigned int exclusive, heartbeat = 0, lobat = 0, lobatunkn = 0;
1094 ALIAS *aliasp;
1095
1096 aliasp = configp->aliasp;
1097
1098 hc = code2hc(hcode);
1099
1100 j = 0;
1101 while ( aliasp && aliasp[j].line_no > 0 ) {
1102 if ( aliasp[j].housecode == hc && (aliasp[j].optflags & MOPT_HEARTBEAT) ) {
1103 heartbeat |= aliasp[j].unitbmap;
1104 }
1105 if ( aliasp[j].housecode == hc && (aliasp[j].optflags & MOPT_LOBAT) ) {
1106 lobat |= aliasp[j].unitbmap;
1107 }
1108 if ( aliasp[j].housecode == hc && (aliasp[j].optflags & MOPT_LOBATUNKN) ) {
1109 lobatunkn |= aliasp[j].unitbmap;
1110 }
1111 j++;
1112 }
1113
1114
1115 printf("Module Attributes\n");
1116 printf("%*s %c\n", lw + 13, "Housecode", hc);
1117 printf("%*s 1..4...8.......16\n", lw, "Unit:");
1118 printf("%*s (%s) %s\n", lw, "On", bmap2asc(modmask[OnMask][hcode], chr),
1119 "Supports On command");
1120 printf("%*s (%s) %s\n", lw, "Off", bmap2asc(modmask[OffMask][hcode], chr),
1121 "Supports Off command");
1122 printf("%*s (%s) %s\n", lw, "Dim", bmap2asc(modmask[DimMask][hcode], chr),
1123 "Supports Dim (1-22) commands");
1124 printf("%*s (%s) %s\n", lw, "Bright", bmap2asc(modmask[BriMask][hcode], chr),
1125 "Supports Bright (1-22) commands");
1126 printf("%*s (%s) %s\n", lw, "BrightB4Dim", bmap2asc(modmask[BriDimMask][hcode], chr),
1127 "Brightens to 100% before Dim/Bright if Off");
1128 printf("%*s (%s) %s\n", lw, "ResumeB4Dim", bmap2asc(modmask[ResumeDimMask][hcode], chr),
1129 "Resumes prev. level before Dim/Bright if Off");
1130 printf("%*s (%s) %s\n", lw, "LightsOn", bmap2asc(modmask[LightsOnMask][hcode], chr),
1131 "Supports LightsOn (AllLightsOn) command");
1132 printf("%*s (%s) %s\n", lw, "LightsOnFull", bmap2asc(modmask[LightsOnFullMask][hcode], chr),
1133 "LightsOn command always brightens to 100%");
1134 printf("%*s (%s) %s\n", lw, "OnFullIfOff", bmap2asc(modmask[OnFullOffMask][hcode], chr),
1135 "LightsOn brightens to 100% only if Off");
1136 exclusive = modmask[Exc16Mask][hcode] | modmask[Exc8Mask][hcode] | modmask[Exc4Mask][hcode];
1137 printf("%*s (%s) %s\n", lw, "ExclusiveOn", bmap2asc(exclusive, chr),
1138 "Last unit turns On, other units in group Off");
1139 printf("%*s (%s) %s\n", lw, "LightsOff", bmap2asc(modmask[LightsOffMask][hcode], chr),
1140 "Supports LightsOff command");
1141 printf("%*s (%s) %s\n", lw, "LiOnUnAddr", bmap2asc(modmask[LightsOnUnaddrMask][hcode], chr),
1142 "Unaddressed by LightsOn command");
1143 printf("%*s (%s) %s\n", lw, "LiOffUnAddr", bmap2asc(modmask[LightsOffUnaddrMask][hcode], chr),
1144 "Unaddressed by LightsOff command");
1145
1146 printf("%*s (%s) %s\n", lw, "OnOffUnAddr", bmap2asc(modmask[OnOffUnaddrMask][hcode], chr),
1147 "Unaddressed by On or Off command");
1148
1149 printf("%*s (%s) %s\n", lw, "AllOff", bmap2asc(modmask[AllOffMask][hcode], chr),
1150 "Supports AllOff (AllUnitsOff) command");
1151 printf("%*s (%s) %s\n", lw, "StatusReq", bmap2asc(modmask[StatusMask][hcode], chr),
1152 "Supports StatusReq command");
1153 printf("%*s (%s) %s\n", lw, "StatusOn", bmap2asc(modmask[StatusOnMask][hcode], chr),
1154 "Sends StatusOn in response to StatusReq");
1155 printf("%*s (%s) %s\n", lw, "StatusOff", bmap2asc(modmask[StatusOffMask][hcode], chr),
1156 "Sends StatusOff in response to StatusReq");
1157 printf("%*s (%s) %s\n", lw, "StatusDefer", bmap2asc(modmask[DeferMask][hcode], chr),
1158 "Defer update until StatusOn/Off response");
1159 printf("%*s (%s) %s\n", lw, "Preset", bmap2asc(modmask[PresetMask][hcode], chr),
1160 "Supports Preset (1-32) commands");
1161 printf("%*s (%s) %s\n", lw, "LevelFixed", bmap2asc(modmask[OnFullMask][hcode], chr),
1162 "On command sets to fixed brightness level");
1163 printf("%*s (%s) %s\n", lw, "LevelResume", bmap2asc(modmask[ResumeMask][hcode], chr),
1164 "On command resumes previous brightness level");
1165 printf("%*s (%s) %s\n", lw, "ExtSwitch", bmap2asc(modmask[Ext3Mask][hcode], chr),
1166 "Supports Extended code switch commands");
1167 printf("%*s (%s) %s\n", lw, "ExtDimmer", bmap2asc(modmask[Ext3DimMask][hcode], chr),
1168 "Supports Extended code dimmer (0-63) commands");
1169 printf("%*s (%s) %s\n", lw, "ExtStatus", bmap2asc(modmask[Ext3StatusMask][hcode], chr),
1170 "Supports Extended code StatusReq commands");
1171 printf("%*s (%s) %s\n", lw, "ExtGrpExec", bmap2asc(modmask[Ext3GrpExecMask][hcode], chr),
1172 "Supports Extended code Group Execute");
1173 printf("%*s (%s) %s\n", lw, "ExtGrpOff",
1174 bmap2asc2(modmask[Ext3GrpOffMask][hcode], modmask[Ext3GrpOffExecMask][hcode], chr),
1175 "Supports Extended code Group Off (x = bug)");
1176 printf("%*s (%s) %s\n", lw, "ExtGrpBrDim", bmap2asc(modmask[Ext3GrpBriDimMask][hcode], chr),
1177 "Supports Extended code Group Bright/Dim");
1178 printf("%*s (%s) %s\n", lw, "ExtGrpRem", bmap2asc(modmask[Ext3GrpRemMask][hcode], chr),
1179 "Supports Extended code Group Remove");
1180 printf("%*s (%s) %s\n", lw, "ExtShutter", bmap2asc(modmask[Ext0Mask][hcode], chr),
1181 "Supports Extended code shutter (0-25) commands");
1182 printf("%*s (%s) %s\n", lw, "PhysMod", bmap2asc((modmask[PhysMask][hcode] | kmodmask[KPhysMask][hcode]), chr),
1183 "Physical receiver module");
1184 printf("%*s (%s) %s\n", lw, "Virtual", bmap2asc(modmask[VdataMask][hcode], chr),
1185 "Virtual Data module");
1186 printf("%*s (%s) %s\n", lw, "PLCSensor", bmap2asc(modmask[PlcSensorMask][hcode], chr),
1187 "Sensor transmits X10 power line signals");
1188 printf("%*s (%s) %s\n", lw, "Security", bmap2asc(vmodmask[VsecMask][hcode], chr),
1189 "X10 Security RF data");
1190 #ifdef HASRFXS
1191 printf("%*s (%s) %s\n", lw, "RFXSensor", bmap2asc(vmodmask[VrfxsMask][hcode], chr),
1192 "RFXSensor RF data");
1193 #endif
1194 #ifdef HASRFXM
1195 printf("%*s (%s) %s\n", lw, "RFXMeter", bmap2asc(vmodmask[VrfxmMask][hcode], chr),
1196 "RFXMeter RF data");
1197 #endif
1198 #ifdef HASDMX
1199 printf("%*s (%s) %s\n", lw, "Digimax", bmap2asc(vmodmask[VdmxMask][hcode], chr),
1200 "Digimax RF data");
1201 #endif
1202 #ifdef HASORE
1203 printf("%*s (%s) %s\n", lw, "Oregon", bmap2asc(vmodmask[VoreMask][hcode], chr),
1204 "Oregon RF data");
1205 #endif
1206 printf("%*s (%s) %s\n", lw, "KaKu/HE", bmap2asc(vmodmask[VkakuMask][hcode], chr),
1207 "Supports KaKu/HomeEasy RF commands");
1208
1209 printf("%*s (%s) %s\n", lw, "Heartbeat", bmap2asc(heartbeat, chr),
1210 "Sensor transmits periodic heartbeat signal");
1211 printf("%*s (%s) %s\n", lw, "LoBat",
1212 bmap2asc2(lobat, lobatunkn, chr2),
1213 "Sensor transmits low battery indication");
1214
1215 printf("\n");
1216
1217 return;
1218 }
1219
1220 /*---------------------------------------------------------------------+
1221 | Count the RF options (There should be no more than one) |
1222 +---------------------------------------------------------------------*/
count_rf_options(ALIAS * aliasp,int aliasindex)1223 int count_rf_options ( ALIAS *aliasp, int aliasindex )
1224 {
1225 int count = 0;
1226
1227 count += (aliasp[aliasindex].optflags & MOPT_TRANSCEIVE) ? 1 : 0;
1228 count += (aliasp[aliasindex].optflags & MOPT_RFFORWARD) ? 1 : 0;
1229 count += (aliasp[aliasindex].optflags & MOPT_RFIGNORE) ? 1 : 0;
1230
1231 return count;
1232 }
1233
1234 /*---------------------------------------------------------------------+
1235 | Set DUMMY option for security remotes (keyfob) |
1236 +---------------------------------------------------------------------*/
remote_options(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1237 int remote_options ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens)
1238 {
1239 int j, k, count = 0;
1240 char *tmptok;
1241 unsigned long flags = 0;
1242
1243 for ( j = 0; j < *ntokens; j++ ) {
1244 strupper(tokens[j]);
1245 if ( strcmp(tokens[j], "DUMMY") == 0 ) {
1246 aliasp[aliasindex].optflags2 |= MOPT2_DUMMY;
1247 *tokens[j] = '\0';
1248 count++;
1249 }
1250 else if ( strcmp(tokens[j], "SWMAX") == 0 ) {
1251 flags |= SEC_MAX;
1252 aliasp[aliasindex].optflags2 |= MOPT2_SWMAX;
1253 *tokens[j] = '\0';
1254 count++;
1255 }
1256 else if ( strcmp(tokens[j], "SWHOME") == 0 ) {
1257 flags |= SEC_HOME;
1258 aliasp[aliasindex].optflags2 |= MOPT2_SWHOME;
1259 *tokens[j] = '\0';
1260 count++;
1261 }
1262 else if ( strcmp(tokens[j], "SWMIN") == 0 ) {
1263 flags |= SEC_MIN;
1264 aliasp[aliasindex].optflags2 &= ~MOPT2_SWMAX;
1265 *tokens[j] = '\0';
1266 count++;
1267 }
1268 else if ( strcmp(tokens[j], "SWAWAY") == 0 ) {
1269 flags |= SEC_AWAY;
1270 aliasp[aliasindex].optflags2 &= ~MOPT2_SWHOME;
1271 *tokens[j] = '\0';
1272 count++;
1273 }
1274 }
1275
1276 if ( flags && (aliasp[aliasindex].optflags2 & MOPT2_DUMMY) ) {
1277 store_error_message("Parameter DUMMY incompatible with SWxxx parameters.");
1278 return 1;
1279 }
1280 if ( (flags & SEC_HOME) && (flags & SEC_AWAY) ) {
1281 store_error_message("Conflicting parameters SWHOME, SWAWAY.");
1282 return 1;
1283 }
1284 if ( (flags & SEC_MAX) && (flags & SEC_MIN) ) {
1285 store_error_message("Conflicting parameters SWMAX, SWMIN.");
1286 return 1;
1287 }
1288
1289
1290 if ( count == 0 )
1291 return 0;
1292
1293 /* Compact to remove "gaps" where tokens were nulled out */
1294
1295 for ( j = 0; j < *ntokens; j++ ) {
1296 if ( *tokens[j] == '\0' ) {
1297 for ( k = j + 1; k < *ntokens; k++ ) {
1298 if ( *tokens[k] != '\0' ) {
1299 tmptok = tokens[j];
1300 tokens[j] = tokens[k];
1301 tokens[k] = tmptok;
1302 *tmptok = '\0';
1303 break;
1304 }
1305 }
1306 }
1307 }
1308
1309 *ntokens -= count;
1310
1311 return 0;
1312 }
1313
1314 /*---------------------------------------------------------------------+
1315 | Set REVERSE, MAIN, and AUX module options |
1316 +---------------------------------------------------------------------*/
sensor_options(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1317 int sensor_options ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens)
1318 {
1319 int j, k, count = 0;
1320 char *tmptok;
1321
1322 for ( j = 0; j < *ntokens; j++ ) {
1323 strupper(tokens[j]);
1324 if ( strcmp(tokens[j], "REVERSE") == 0 ) {
1325 aliasp[aliasindex].optflags |= MOPT_REVERSE;
1326 *tokens[j] = '\0';
1327 count++;
1328 }
1329 else if ( strcmp(tokens[j], "RFIGNORE") == 0 ) {
1330 aliasp[aliasindex].optflags |= MOPT_RFIGNORE;
1331 *tokens[j] = '\0';
1332 count++;
1333 }
1334 else if ( strcmp(tokens[j], "MAIN") == 0 ) {
1335 aliasp[aliasindex].optflags |= MOPT_MAIN;
1336 *tokens[j] = '\0';
1337 count++;
1338 }
1339 else if ( strcmp(tokens[j], "AUX") == 0 ) {
1340 aliasp[aliasindex].optflags |= MOPT_AUX;
1341 *tokens[j] = '\0';
1342 count++;
1343 }
1344 }
1345
1346 /* Compact to remove "gaps" where tokens were nulled out */
1347
1348 for ( j = 0; j < *ntokens; j++ ) {
1349 if ( *tokens[j] == '\0' ) {
1350 for ( k = j + 1; k < *ntokens; k++ ) {
1351 if ( *tokens[k] != '\0' ) {
1352 tmptok = tokens[j];
1353 tokens[j] = tokens[k];
1354 tokens[k] = tmptok;
1355 *tmptok = '\0';
1356 break;
1357 }
1358 }
1359 }
1360 }
1361
1362 *ntokens -= count;
1363
1364 return 0;
1365 }
1366
1367 /*---------------------------------------------------------------------+
1368 | Options for PLC Sensor |
1369 +---------------------------------------------------------------------*/
opt_plcsensor(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1370 int opt_plcsensor ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens)
1371 {
1372
1373 if ( sensor_timeout(aliasp, aliasindex, tokens, ntokens) != 0 )
1374 return 1;
1375
1376 aliasp[aliasindex].vtype = 0;
1377 aliasp[aliasindex].optflags |= (MOPT_PLCSENSOR | MOPT_HEARTBEAT);
1378 return 0;
1379 }
1380
1381 /*---------------------------------------------------------------------+
1382 | Options for second sensor in RFXSensor modules |
1383 +---------------------------------------------------------------------*/
opt_rfxsensor(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1384 int opt_rfxsensor ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens)
1385 {
1386 long ident;
1387 unsigned char rfxid /*, delta */;
1388 char *sp;
1389
1390 if ( sensor_timeout(aliasp, aliasindex, tokens, ntokens) != 0 )
1391 return 1;
1392
1393 if ( *ntokens < 2 ) {
1394 store_error_message("This module requires more parameters.");
1395 return 1;
1396 }
1397
1398 if ( single_bmap_unit(aliasp[aliasindex].unitbmap) == 0xff ) {
1399 store_error_message("Multiple unit alias is invalid for sensors.");
1400 return 1;
1401 }
1402
1403 ident = strtol(tokens[0], &sp, 16);
1404 if ( *sp == '\0' && ident >= 0 && ident <= 0xff ) {
1405 aliasp[aliasindex].ident[0] = (unsigned short)ident;
1406 }
1407 else {
1408 store_error_message("Invalid hexadecimal RFXSensor base address parameter");
1409 return 1;
1410 }
1411
1412 rfxid = aliasp[aliasindex].ident[0];
1413
1414 if ( (rfxid % 4) != 0 ) {
1415 store_error_message("RFXSensor base address must be a multiple of 0x04");
1416 return 1;
1417 }
1418
1419 /* Add IDs for secondary and Supply Voltage sensors. */
1420 aliasp[aliasindex].ident[1] = aliasp[aliasindex].ident[0] + 1;
1421 aliasp[aliasindex].ident[2] = aliasp[aliasindex].ident[0] + 2;
1422 aliasp[aliasindex].nident = 3;
1423
1424 aliasp[aliasindex].optflags |= MOPT_RFXVS;
1425
1426 strupper(tokens[1]);
1427 if ( strcmp(tokens[1], "TH") == 0 ) {
1428 /* Temperature and Humidity */
1429 aliasp[aliasindex].optflags |= MOPT_RFXRH;
1430 }
1431 else if ( strcmp(tokens[1], "TB") == 0 ) {
1432 /* Temperature and Barometric Pressure */
1433 aliasp[aliasindex].optflags |= MOPT_RFXBP;
1434 }
1435 else if ( strcmp(tokens[1], "TV") == 0 ) {
1436 /* Temperature and Voltage */
1437 aliasp[aliasindex].optflags |= MOPT_RFXVAD;
1438 }
1439 else if ( strcmp(tokens[1], "TP") == 0 ) {
1440 /* Potentiometer */
1441 aliasp[aliasindex].optflags |= MOPT_RFXPOT;
1442 }
1443 else if ( strcmp(tokens[1], "TT") == 0 ) {
1444 /* Two Temperature probes */
1445 aliasp[aliasindex].optflags |= MOPT_RFXT2;
1446 }
1447 else if ( strcmp(tokens[1], "T") == 0 ) {
1448 /* Single Temperature probe */
1449 aliasp[aliasindex].optflags &= ~MOPT_RFXVS;
1450 }
1451 else {
1452 store_error_message("Invalid RFXSensor function.");
1453 return 1;
1454 }
1455
1456 /* This is a sensor with periodic "heartbeat" signals */
1457 aliasp[aliasindex].vtype = RF_XSENSOR;
1458 aliasp[aliasindex].optflags |= (MOPT_RFXSENSOR | MOPT_HEARTBEAT | MOPT_LOBAT);
1459
1460 return 0;
1461 }
1462
1463 /*---------------------------------------------------------------------+
1464 | Options for RFXMeter modules |
1465 +---------------------------------------------------------------------*/
opt_rfxmeter(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1466 int opt_rfxmeter ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens)
1467 {
1468 long ident;
1469 char *sp;
1470
1471 if ( sensor_timeout(aliasp, aliasindex, tokens, ntokens) != 0 )
1472 return 1;
1473
1474 if ( *ntokens < 1 ) {
1475 store_error_message("This module requires one ID parameter.");
1476 return 1;
1477 }
1478 else if ( *ntokens > 1 ) {
1479 store_error_message("This module accepts only one ID parameter.");
1480 return 1;
1481 }
1482
1483 ident = strtol(tokens[0], &sp, 16);
1484 if ( *sp == '\0' && ident >= 0 && ident <= 0xff ) {
1485 aliasp[aliasindex].ident[0] = (unsigned short)ident;
1486 }
1487 else {
1488 store_error_message("Invalid hexadecimal RFXMeter ID parameter");
1489 return 1;
1490 }
1491 aliasp[aliasindex].nident = 1;
1492
1493 aliasp[aliasindex].vtype = RF_XMETER;
1494 aliasp[aliasindex].optflags |= ((MOPT_SENSOR | MOPT_HEARTBEAT) & ~MOPT_LOBAT);
1495
1496 return 0;
1497 }
1498
1499 /*---------------------------------------------------------------------+
1500 | Options for RFXMeter Pulse modules |
1501 +---------------------------------------------------------------------*/
opt_rfxpulse(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1502 int opt_rfxpulse ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens)
1503 {
1504 if ( opt_rfxmeter(aliasp, aliasindex, tokens, ntokens) != 0 )
1505 return 1;
1506
1507 aliasp[aliasindex].optflags |= (MOPT_RFXPULSE | MOPT_RFXCOUNT | MOPT_HEARTBEAT);
1508 return 0;
1509 }
1510
1511 /*---------------------------------------------------------------------+
1512 | Options for RFXMeter Counter modules |
1513 +---------------------------------------------------------------------*/
opt_rfxcount(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1514 int opt_rfxcount ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens)
1515 {
1516 if ( opt_rfxmeter(aliasp, aliasindex, tokens, ntokens) != 0 )
1517 return 1;
1518
1519 aliasp[aliasindex].optflags |= (MOPT_RFXCOUNT | MOPT_HEARTBEAT);
1520 return 0;
1521 }
1522
1523 /*---------------------------------------------------------------------+
1524 | Options for RFXMeter Power modules |
1525 +---------------------------------------------------------------------*/
opt_rfxpower(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1526 int opt_rfxpower ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens)
1527 {
1528 if ( opt_rfxmeter(aliasp, aliasindex, tokens, ntokens) != 0 )
1529 return 1;
1530
1531 aliasp[aliasindex].optflags |= (MOPT_RFXPOWER | MOPT_RFXCOUNT | MOPT_HEARTBEAT);
1532 return 0;
1533 }
1534
1535 /*---------------------------------------------------------------------+
1536 | Options for RFXMeter Water meter modules |
1537 +---------------------------------------------------------------------*/
opt_rfxwater(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1538 int opt_rfxwater ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens)
1539 {
1540 if ( opt_rfxmeter(aliasp, aliasindex, tokens, ntokens) != 0 )
1541 return 1;
1542
1543 aliasp[aliasindex].optflags |= (MOPT_RFXWATER | MOPT_RFXCOUNT | MOPT_HEARTBEAT);
1544 return 0;
1545 }
1546
1547 /*---------------------------------------------------------------------+
1548 | Options for RFXMeter Gas meter modules |
1549 +---------------------------------------------------------------------*/
opt_rfxgas(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1550 int opt_rfxgas ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens)
1551 {
1552 if ( opt_rfxmeter(aliasp, aliasindex, tokens, ntokens) != 0 )
1553 return 1;
1554
1555 aliasp[aliasindex].optflags |= (MOPT_RFXGAS | MOPT_RFXCOUNT | MOPT_HEARTBEAT);
1556 return 0;
1557 }
1558
1559 /*---------------------------------------------------------------------+
1560 | Options for Digimax 210 |
1561 +---------------------------------------------------------------------*/
opt_digimax(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1562 int opt_digimax ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1563 {
1564 long ident;
1565 char *sp;
1566
1567 if ( *ntokens < 1 ) {
1568 store_error_message("This module requires an ID parameter");
1569 return 1;
1570 }
1571
1572 if ( single_bmap_unit(aliasp[aliasindex].unitbmap) == 0xff ) {
1573 store_error_message("Multiple unit alias is invalid for sensors.");
1574 return 1;
1575 }
1576
1577 ident = strtol(tokens[0], &sp, 16);
1578 if ( *sp == '\0' && ident >= 0 && ident <= 0xffff ) {
1579 aliasp[aliasindex].ident[0] = (unsigned short)ident;
1580 aliasp[aliasindex].nident = 1;
1581 }
1582 else {
1583 store_error_message("Invalid hexadecimal Digimax address parameter");
1584 return 1;
1585 }
1586
1587 if ( sensor_timeout(aliasp, aliasindex, tokens, ntokens) != 0 )
1588 return 1;
1589
1590 aliasp[aliasindex].vtype = RF_DIGIMAX;
1591 aliasp[aliasindex].storage_units = 1;
1592
1593 aliasp[aliasindex].optflags = (MOPT_SECURITY | MOPT_SENSOR | MOPT_HEARTBEAT);
1594
1595 return 0;
1596 }
1597
1598 /*---------------------------------------------------------------------+
1599 | Options for ACT modules. |
1600 +---------------------------------------------------------------------*/
opt_act(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1601 int opt_act ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1602 {
1603 int j;
1604 char message[80];
1605
1606 for ( j = 0; j < *ntokens; j++ ) {
1607 strupper(tokens[j]);
1608 if ( strcmp(tokens[j], "AUF") == 0 )
1609 aliasp[aliasindex].optflags2 |= MOPT2_AUF;
1610 else if ( strcmp(tokens[j], "ALO") == 0 )
1611 aliasp[aliasindex].optflags2 |= MOPT2_ALO;
1612 else if ( strcmp(tokens[j], "ALF") == 0 )
1613 aliasp[aliasindex].optflags2 |= MOPT2_ALF;
1614 else {
1615 sprintf(message, "Invalid module option '%s'", tokens[j]);
1616 store_error_message(message);
1617 return 1;
1618 }
1619 }
1620
1621 return 0;
1622 }
1623
1624 /*---------------------------------------------------------------------+
1625 | Option for 2-way modules with automatic StatusOn/Off response |
1626 +---------------------------------------------------------------------*/
opt_defer(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1627 int opt_defer ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1628 {
1629 int j;
1630 char message[80];
1631
1632 for ( j = 0; j < *ntokens; j++ ) {
1633 strupper(tokens[j]);
1634 if ( strcmp(tokens[j], "DEFER") == 0 )
1635 aliasp[aliasindex].optflags2 |= MOPT2_DEFER;
1636 else {
1637 sprintf(message, "Invalid module option '%s'", tokens[j]);
1638 store_error_message(message);
1639 return 1;
1640 }
1641 }
1642
1643 return 0;
1644 }
1645
1646
1647 #ifdef HASORE
1648 /*---------------------------------------------------------------------+
1649 | General options for Oregon sensors |
1650 +---------------------------------------------------------------------*/
opt_oregon(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1651 int opt_oregon ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1652 {
1653 long ident;
1654 char *sp;
1655
1656 if ( ore_maxmin_temp(aliasp, aliasindex, tokens, ntokens) != 0 )
1657 return 1;
1658 if ( ore_maxmin_rh(aliasp, aliasindex, tokens, ntokens) != 0 )
1659 return 1;
1660 if ( ore_maxmin_bp(aliasp, aliasindex, tokens, ntokens) != 0 )
1661 return 1;
1662 if ( sensor_timeout(aliasp, aliasindex, tokens, ntokens) != 0 )
1663 return 1;
1664
1665 if ( *ntokens != 1 ) {
1666 store_error_message("Unknown parameters");
1667 return 1;
1668 }
1669
1670 if ( single_bmap_unit(aliasp[aliasindex].unitbmap) == 0xff ) {
1671 store_error_message("Multiple unit alias is invalid for sensors.");
1672 return 1;
1673 }
1674
1675 ident = strtol(tokens[0], &sp, 16);
1676 if ( *sp == '\0' && ident >= 0 && ident <= 0xfff ) {
1677 aliasp[aliasindex].ident[0] = (unsigned short)ident;
1678 aliasp[aliasindex].nident = 1;
1679 }
1680 else {
1681 store_error_message("Invalid hexadecimal Oregon address parameter");
1682 return 1;
1683 }
1684
1685 aliasp[aliasindex].vtype = RF_OREGON;
1686
1687 aliasp[aliasindex].optflags = (MOPT_SECURITY | MOPT_SENSOR | MOPT_HEARTBEAT | MOPT_LOBAT);
1688
1689 return 0;
1690 }
1691
1692 /*---------------------------------------------------------------------+
1693 | General options for Oregon sensors |
1694 +---------------------------------------------------------------------*/
opt_ore_dummy(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1695 int opt_ore_dummy ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1696 {
1697
1698 if ( ore_maxmin_temp(aliasp, aliasindex, tokens, ntokens) != 0 )
1699 return 1;
1700 if ( ore_maxmin_rh(aliasp, aliasindex, tokens, ntokens) != 0 )
1701 return 1;
1702 if ( ore_maxmin_bp(aliasp, aliasindex, tokens, ntokens) != 0 )
1703 return 1;
1704 if ( sensor_timeout(aliasp, aliasindex, tokens, ntokens) != 0 )
1705 return 1;
1706
1707
1708 if ( *ntokens != 0 ) {
1709 store_error_message("Unknown parameters");
1710 return 1;
1711 }
1712
1713 if ( single_bmap_unit(aliasp[aliasindex].unitbmap) == 0xff ) {
1714 store_error_message("Multiple unit alias is invalid for sensors.");
1715 return 1;
1716 }
1717
1718 aliasp[aliasindex].nident = 0;
1719
1720 aliasp[aliasindex].vtype = RF_OREGON;
1721
1722 aliasp[aliasindex].optflags = (MOPT_SECURITY | MOPT_SENSOR | MOPT_HEARTBEAT);
1723
1724 return 0;
1725 }
1726
1727 /*---------------------------------------------------------------------+
1728 | Options for Oregon Temp1 sensors |
1729 +---------------------------------------------------------------------*/
opt_oreTemp1(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1730 int opt_oreTemp1 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1731 {
1732 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1733 return 1;
1734
1735 aliasp[aliasindex].subtype = OreTemp1;
1736 aliasp[aliasindex].nvar = 1;
1737 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
1738 aliasp[aliasindex].funclist[0] = OreTempFunc;
1739
1740 return 0;
1741 }
1742
1743 /*---------------------------------------------------------------------+
1744 | Options for Oregon Temp2 sensors |
1745 +---------------------------------------------------------------------*/
opt_oreTemp2(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1746 int opt_oreTemp2 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1747 {
1748 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1749 return 1;
1750
1751 aliasp[aliasindex].subtype = OreTemp2;
1752 aliasp[aliasindex].nvar = 1;
1753 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
1754 aliasp[aliasindex].funclist[0] = OreTempFunc;
1755
1756 return 0;
1757 }
1758
1759 /*---------------------------------------------------------------------+
1760 | Options for Oregon Temp3 sensors |
1761 +---------------------------------------------------------------------*/
opt_oreTemp3(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1762 int opt_oreTemp3 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1763 {
1764 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1765 return 1;
1766
1767 aliasp[aliasindex].subtype = OreTemp3;
1768 aliasp[aliasindex].nvar = 1;
1769 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
1770 aliasp[aliasindex].funclist[0] = OreTempFunc;
1771
1772 return 0;
1773 }
1774
1775 /*---------------------------------------------------------------------+
1776 | Options for Oregon TH1 sensors |
1777 +---------------------------------------------------------------------*/
opt_oreTH1(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1778 int opt_oreTH1 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1779 {
1780 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1781 return 1;
1782
1783 aliasp[aliasindex].subtype = OreTH1;
1784 aliasp[aliasindex].nvar = 2;
1785 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
1786 aliasp[aliasindex].funclist[0] = OreTempFunc;
1787 aliasp[aliasindex].funclist[1] = OreHumidFunc;
1788
1789 return 0;
1790 }
1791
1792 /*---------------------------------------------------------------------+
1793 | Options for Oregon TH2 sensors |
1794 +---------------------------------------------------------------------*/
opt_oreTH2(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1795 int opt_oreTH2 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1796 {
1797 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1798 return 1;
1799
1800 aliasp[aliasindex].subtype = OreTH2;
1801 aliasp[aliasindex].nvar = 2;
1802 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
1803 aliasp[aliasindex].funclist[0] = OreTempFunc;
1804 aliasp[aliasindex].funclist[1] = OreHumidFunc;
1805
1806 return 0;
1807 }
1808
1809 /*---------------------------------------------------------------------+
1810 | Options for Oregon TH3 sensors |
1811 +---------------------------------------------------------------------*/
opt_oreTH3(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1812 int opt_oreTH3 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1813 {
1814 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1815 return 1;
1816
1817 aliasp[aliasindex].subtype = OreTH3;
1818 aliasp[aliasindex].nvar = 2;
1819 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
1820 aliasp[aliasindex].funclist[0] = OreTempFunc;
1821 aliasp[aliasindex].funclist[1] = OreHumidFunc;
1822
1823 return 0;
1824 }
1825
1826 /*---------------------------------------------------------------------+
1827 | Options for Oregon TH4 sensors |
1828 +---------------------------------------------------------------------*/
opt_oreTH4(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1829 int opt_oreTH4 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1830 {
1831 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1832 return 1;
1833
1834 aliasp[aliasindex].subtype = OreTH4;
1835 aliasp[aliasindex].nvar = 2;
1836 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
1837 aliasp[aliasindex].funclist[0] = OreTempFunc;
1838 aliasp[aliasindex].funclist[1] = OreHumidFunc;
1839
1840 return 0;
1841 }
1842
1843 /*---------------------------------------------------------------------+
1844 | Options for Oregon TH5 sensors |
1845 +---------------------------------------------------------------------*/
opt_oreTH5(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1846 int opt_oreTH5 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1847 {
1848 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1849 return 1;
1850
1851 aliasp[aliasindex].subtype = OreTH5;
1852 aliasp[aliasindex].nvar = 2;
1853 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
1854 aliasp[aliasindex].funclist[0] = OreTempFunc;
1855 aliasp[aliasindex].funclist[1] = OreHumidFunc;
1856
1857 return 0;
1858 }
1859
1860 /*---------------------------------------------------------------------+
1861 | Options for Oregon TH6 sensors |
1862 +---------------------------------------------------------------------*/
opt_oreTH6(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1863 int opt_oreTH6 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1864 {
1865 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1866 return 1;
1867
1868 aliasp[aliasindex].subtype = OreTH6;
1869 aliasp[aliasindex].nvar = 2;
1870 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
1871 aliasp[aliasindex].funclist[0] = OreTempFunc;
1872 aliasp[aliasindex].funclist[1] = OreHumidFunc;
1873
1874 return 0;
1875 }
1876
1877 /*---------------------------------------------------------------------+
1878 | Options for Oregon THB1 sensors |
1879 +---------------------------------------------------------------------*/
opt_oreTHB1(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1880 int opt_oreTHB1 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1881 {
1882 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1883 return 1;
1884
1885 aliasp[aliasindex].subtype = OreTHB1;
1886 aliasp[aliasindex].nvar = 3;
1887 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
1888 aliasp[aliasindex].funclist[0] = OreTempFunc;
1889 aliasp[aliasindex].funclist[1] = OreHumidFunc;
1890 aliasp[aliasindex].funclist[2] = OreBaroFunc;
1891
1892 return 0;
1893 }
1894
1895 /*---------------------------------------------------------------------+
1896 | Options for Oregon THB2 sensors |
1897 +---------------------------------------------------------------------*/
opt_oreTHB2(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1898 int opt_oreTHB2 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1899 {
1900 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1901 return 1;
1902
1903 aliasp[aliasindex].subtype = OreTHB2;
1904 aliasp[aliasindex].nvar = 3;
1905 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
1906 aliasp[aliasindex].funclist[0] = OreTempFunc;
1907 aliasp[aliasindex].funclist[1] = OreHumidFunc;
1908 aliasp[aliasindex].funclist[2] = OreBaroFunc;
1909
1910 return 0;
1911 }
1912
1913 /*---------------------------------------------------------------------+
1914 | Options for Oregon Wind1 sensors |
1915 +---------------------------------------------------------------------*/
opt_oreWind1(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1916 int opt_oreWind1 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1917 {
1918 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1919 return 1;
1920
1921 aliasp[aliasindex].subtype = OreWind1;
1922 aliasp[aliasindex].nvar = 3;
1923 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
1924 aliasp[aliasindex].funclist[0] = OreWindAvSpFunc;
1925 aliasp[aliasindex].funclist[1] = OreWindSpFunc;
1926 aliasp[aliasindex].funclist[2] = OreWindDirFunc;
1927
1928 return 0;
1929 }
1930
1931 /*---------------------------------------------------------------------+
1932 | Options for Oregon Wind2 sensors |
1933 +---------------------------------------------------------------------*/
opt_oreWind2(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1934 int opt_oreWind2 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1935 {
1936 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1937 return 1;
1938
1939 aliasp[aliasindex].subtype = OreWind2;
1940 aliasp[aliasindex].nvar = 3;
1941 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
1942 aliasp[aliasindex].funclist[0] = OreWindAvSpFunc;
1943 aliasp[aliasindex].funclist[1] = OreWindSpFunc;
1944 aliasp[aliasindex].funclist[2] = OreWindDirFunc;
1945
1946 return 0;
1947 }
1948
1949 /*---------------------------------------------------------------------+
1950 | Options for Oregon Wind3 sensors |
1951 +---------------------------------------------------------------------*/
opt_oreWind3(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1952 int opt_oreWind3 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1953 {
1954 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1955 return 1;
1956
1957 aliasp[aliasindex].subtype = OreWind3;
1958 aliasp[aliasindex].nvar = 3;
1959 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
1960 aliasp[aliasindex].funclist[0] = OreWindAvSpFunc;
1961 aliasp[aliasindex].funclist[1] = OreWindSpFunc;
1962 aliasp[aliasindex].funclist[2] = OreWindDirFunc;
1963
1964 return 0;
1965 }
1966
1967 /*---------------------------------------------------------------------+
1968 | Options for Oregon Rain1 sensors |
1969 +---------------------------------------------------------------------*/
opt_oreRain1(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1970 int opt_oreRain1 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1971 {
1972 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1973 return 1;
1974
1975 aliasp[aliasindex].subtype = OreRain1;
1976 aliasp[aliasindex].nvar = 2;
1977 /* Need extra storage locations for 32 bit data */
1978 aliasp[aliasindex].storage_units = 4 * aliasp[aliasindex].nvar;
1979 aliasp[aliasindex].funclist[0] = OreRainRateFunc;
1980 aliasp[aliasindex].funclist[1] = OreRainTotFunc;
1981 /* Override the default storage offsets */
1982 aliasp[aliasindex].statusoffset[0] = 0;
1983 aliasp[aliasindex].statusoffset[1] = 4;
1984
1985 return 0;
1986 }
1987
1988 /*---------------------------------------------------------------------+
1989 | Options for Oregon Rain2 sensors |
1990 +---------------------------------------------------------------------*/
opt_oreRain2(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)1991 int opt_oreRain2 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
1992 {
1993 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
1994 return 1;
1995
1996 aliasp[aliasindex].subtype = OreRain2;
1997 aliasp[aliasindex].nvar = 2;
1998 /* Need extra storage locations for 32 bit data */
1999 aliasp[aliasindex].storage_units = 4 * aliasp[aliasindex].nvar;
2000 aliasp[aliasindex].funclist[0] = OreRainRateFunc;
2001 aliasp[aliasindex].funclist[1] = OreRainTotFunc;
2002 /* Override the default storage offsets */
2003 aliasp[aliasindex].statusoffset[0] = 0;
2004 aliasp[aliasindex].statusoffset[1] = 4;
2005
2006 return 0;
2007 }
2008
2009 /*---------------------------------------------------------------------+
2010 | Options for Oregon Rain3 sensors |
2011 +---------------------------------------------------------------------*/
opt_oreRain3(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2012 int opt_oreRain3 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2013 {
2014 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
2015 return 1;
2016
2017 aliasp[aliasindex].subtype = OreRain3;
2018 aliasp[aliasindex].nvar = 2;
2019 /* Need extra storage locations for 32 bit data */
2020 aliasp[aliasindex].storage_units = 4 * aliasp[aliasindex].nvar;
2021 aliasp[aliasindex].funclist[0] = OreRainRateFunc;
2022 aliasp[aliasindex].funclist[1] = OreRainTotFunc;
2023 /* Override the default storage offsets */
2024 aliasp[aliasindex].statusoffset[0] = 0;
2025 aliasp[aliasindex].statusoffset[1] = 4;
2026
2027 return 0;
2028 }
2029
2030 /*---------------------------------------------------------------------+
2031 | Options for Electrisave sensors |
2032 +---------------------------------------------------------------------*/
opt_elsElec1(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2033 int opt_elsElec1 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2034 {
2035 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
2036 return 1;
2037
2038 aliasp[aliasindex].vtype = RF_ELECSAVE;
2039 aliasp[aliasindex].subtype = OreElec1;
2040 aliasp[aliasindex].nvar = 1;
2041 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
2042 aliasp[aliasindex].funclist[0] = ElsCurrFunc;
2043
2044 return 0;
2045 }
2046
2047 /*---------------------------------------------------------------------+
2048 | Options for OWL CM119 sensors |
2049 +---------------------------------------------------------------------*/
opt_owlElec2(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2050 int opt_owlElec2 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2051 {
2052 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
2053 return 1;
2054
2055 /* OWL needs 2 storage locations for power and 3 storage locations */
2056 /* for energy - all times 2 for last unchanged values also. */
2057
2058 aliasp[aliasindex].vtype = RF_OWL;
2059 aliasp[aliasindex].subtype = OreElec2;
2060 aliasp[aliasindex].nvar = 2;
2061 aliasp[aliasindex].storage_units = 10;
2062 aliasp[aliasindex].funclist[0] = OwlPowerFunc;
2063 aliasp[aliasindex].funclist[1] = OwlEnergyFunc;
2064 /* Override the default storage offsets */
2065 aliasp[aliasindex].statusoffset[0] = 0;
2066 aliasp[aliasindex].statusoffset[1] = 2;
2067
2068 aliasp[aliasindex].optflags &= ~MOPT_LOBAT;
2069 aliasp[aliasindex].optflags |= MOPT_LOBATUNKN;
2070
2071 return 0;
2072 }
2073
2074 /*---------------------------------------------------------------------+
2075 | Options for OWL CM119 sensors |
2076 +---------------------------------------------------------------------*/
opt_owlElec2new(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2077 int opt_owlElec2new ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2078 {
2079 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
2080 return 1;
2081
2082 /* OWL needs 2 storage locations for power and 3 storage locations */
2083 /* for energy - all times 2 for last unchanged values also. */
2084
2085 aliasp[aliasindex].vtype = RF_OWL;
2086 aliasp[aliasindex].subtype = OreElec2;
2087 aliasp[aliasindex].nvar = 2;
2088 aliasp[aliasindex].storage_units = 10;
2089 aliasp[aliasindex].funclist[0] = OwlPowerFunc;
2090 aliasp[aliasindex].funclist[1] = OwlEnergyFunc;
2091 /* Override the default storage offsets */
2092 aliasp[aliasindex].statusoffset[0] = 0;
2093 aliasp[aliasindex].statusoffset[1] = 4;
2094
2095 aliasp[aliasindex].optflags &= ~MOPT_LOBAT;
2096 aliasp[aliasindex].optflags |= MOPT_LOBATUNKN;
2097
2098 return 0;
2099 }
2100
2101 /*---------------------------------------------------------------------+
2102 | Options for OWL CM119 sensors |
2103 +---------------------------------------------------------------------*/
opt_owlElec2rev(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2104 int opt_owlElec2rev ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2105 {
2106 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
2107 return 1;
2108
2109 /* OWL needs 2 storage locations for power and 3 storage locations */
2110 /* for energy - all times 2 for last unchanged values also. */
2111
2112 aliasp[aliasindex].vtype = RF_OWL;
2113 aliasp[aliasindex].subtype = OreElec2;
2114 aliasp[aliasindex].nvar = 2;
2115 aliasp[aliasindex].storage_units = 10;
2116 aliasp[aliasindex].funclist[0] = OwlEnergyFunc;
2117 aliasp[aliasindex].funclist[1] = OwlPowerFunc;
2118 /* Override the default storage offsets */
2119 aliasp[aliasindex].statusoffset[0] = 4;
2120 aliasp[aliasindex].statusoffset[1] = 0;
2121
2122 aliasp[aliasindex].optflags &= ~MOPT_LOBAT;
2123 aliasp[aliasindex].optflags |= MOPT_LOBATUNKN;
2124
2125 return 0;
2126 }
2127
2128 /*---------------------------------------------------------------------+
2129 | Options for Oregon UV1 sensors |
2130 +---------------------------------------------------------------------*/
opt_oreUV1(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2131 int opt_oreUV1 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2132 {
2133 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
2134 return 1;
2135
2136 aliasp[aliasindex].subtype = OreUV1;
2137 aliasp[aliasindex].nvar = 1;
2138 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
2139 aliasp[aliasindex].funclist[0] = OreUVFunc;
2140
2141 return 0;
2142 }
2143
2144 /*---------------------------------------------------------------------+
2145 | Options for Oregon UV2 sensors |
2146 +---------------------------------------------------------------------*/
opt_oreUV2(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2147 int opt_oreUV2 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2148 {
2149 if ( opt_oregon(aliasp, aliasindex, tokens, ntokens) != 0 )
2150 return 1;
2151
2152 aliasp[aliasindex].subtype = OreUV2;
2153 aliasp[aliasindex].nvar = 1;
2154 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
2155 aliasp[aliasindex].funclist[0] = OreUVFunc;
2156
2157 return 0;
2158 }
2159
2160 /*---------------------------------------------------------------------+
2161 | Options for Oregon WEIGHT1 sensors |
2162 +---------------------------------------------------------------------*/
opt_oreWeight1(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2163 int opt_oreWeight1 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2164 {
2165 long ident;
2166 char *sp;
2167
2168 if ( *ntokens != 1 ) {
2169 store_error_message("Unknown parameters");
2170 return 1;
2171 }
2172
2173 if ( single_bmap_unit(aliasp[aliasindex].unitbmap) == 0xff ) {
2174 store_error_message("Multiple unit alias is invalid for sensors.");
2175 return 1;
2176 }
2177
2178 ident = strtol(tokens[0], &sp, 16);
2179 if ( *sp == '\0' && ident >= 0 && ident <= 0xfff ) {
2180 aliasp[aliasindex].ident[0] = (unsigned short)ident;
2181 aliasp[aliasindex].nident = 1;
2182 }
2183 else {
2184 store_error_message("Invalid hexadecimal Oregon address parameter");
2185 return 1;
2186 }
2187
2188 aliasp[aliasindex].vtype = RF_OREGON;
2189 aliasp[aliasindex].subtype = OreWeight1;
2190 aliasp[aliasindex].optflags = (MOPT_SECURITY | MOPT_SENSOR);
2191 aliasp[aliasindex].nvar = 1;
2192 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
2193 aliasp[aliasindex].funclist[0] = OreWeightFunc;
2194
2195 return 0;
2196 }
2197
2198 /*---------------------------------------------------------------------+
2199 | Options for Oregon Dummy Temp sensors |
2200 +---------------------------------------------------------------------*/
opt_oreTemu(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2201 int opt_oreTemu ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2202 {
2203 if ( opt_ore_dummy(aliasp, aliasindex, tokens, ntokens) != 0 )
2204 return 1;
2205
2206 aliasp[aliasindex].subtype = OreTemu;
2207 aliasp[aliasindex].nvar = 1;
2208 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
2209 aliasp[aliasindex].funclist[0] = OreTempFunc;
2210
2211 return 0;
2212 }
2213
2214 /*---------------------------------------------------------------------+
2215 | Options for Oregon Dummy Temp/Humidity sensors |
2216 +---------------------------------------------------------------------*/
opt_oreTHemu(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2217 int opt_oreTHemu ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2218 {
2219 if ( opt_ore_dummy(aliasp, aliasindex, tokens, ntokens) != 0 )
2220 return 1;
2221
2222 aliasp[aliasindex].subtype = OreTHemu;
2223 aliasp[aliasindex].nvar = 2;
2224 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
2225 aliasp[aliasindex].funclist[0] = OreTempFunc;
2226 aliasp[aliasindex].funclist[1] = OreHumidFunc;
2227
2228 return 0;
2229 }
2230
2231 /*---------------------------------------------------------------------+
2232 | Options for Oregon Dummy THB sensors |
2233 +---------------------------------------------------------------------*/
opt_oreTHBemu(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2234 int opt_oreTHBemu ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2235 {
2236 if ( opt_ore_dummy(aliasp, aliasindex, tokens, ntokens) != 0 )
2237 return 1;
2238
2239 aliasp[aliasindex].subtype = OreTHBemu;
2240 aliasp[aliasindex].nvar = 3;
2241 aliasp[aliasindex].storage_units = 2 * aliasp[aliasindex].nvar;
2242 aliasp[aliasindex].funclist[0] = OreTempFunc;
2243 aliasp[aliasindex].funclist[1] = OreHumidFunc;
2244 aliasp[aliasindex].funclist[2] = OreBaroFunc;
2245
2246 return 0;
2247 }
2248
2249 /*-------------------------------------------------------+
2250 | Called for Oregon sensor IDs which are to be ignored |
2251 +-------------------------------------------------------*/
opt_oreignore(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2252 int opt_oreignore ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2253 {
2254 char *sp;
2255 long ident;
2256 int j;
2257
2258 /* First token is security ID */
2259 if ( *ntokens < 1 ) {
2260 store_error_message("Module ID(s) needed.");
2261 return 1;
2262 }
2263 if ( *ntokens > NIDENT ) {
2264 store_error_message("Too many parameters on line.");
2265 return 1;
2266 }
2267
2268 for ( j = 0; j < *ntokens; j++ ) {
2269 ident = strtol(tokens[j], &sp, 16);
2270 if ( *sp == '\0' && ident >= 0 && ident <= 0xffff ) { /* Was 0xaff ??? */
2271 aliasp[aliasindex].ident[j] = (unsigned short)ident;
2272 }
2273 else {
2274 store_error_message("Invalid hexadecimal ID parameter");
2275 return 1;
2276 }
2277 }
2278 aliasp[aliasindex].nident = j;
2279
2280 /* This is a security RF transmitter */
2281 aliasp[aliasindex].vtype = RF_OREGON;
2282 aliasp[aliasindex].optflags = (MOPT_SECURITY | MOPT_RFIGNORE);
2283
2284 return 0;
2285 }
2286
2287 #endif
2288
2289 /*--------------------------------------------------------+
2290 | Called for Security sensor IDs which are to be ignored |
2291 +--------------------------------------------------------*/
opt_secignore(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2292 int opt_secignore ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2293 {
2294 char *sp;
2295 long ident;
2296 int j;
2297
2298 /* First token is security ID */
2299 if ( *ntokens < 1 ) {
2300 store_error_message("Module ID(s) needed.");
2301 return 1;
2302 }
2303 if ( *ntokens > NIDENT ) {
2304 store_error_message("Too many parameters on line.");
2305 return 1;
2306 }
2307
2308 for ( j = 0; j < *ntokens; j++ ) {
2309 ident = strtol(tokens[j], &sp, 16);
2310 if ( *sp == '\0' && ident >= 0 && ident <= 0xffff ) {
2311 aliasp[aliasindex].ident[j] = (unsigned short)ident;
2312 }
2313 else {
2314 store_error_message("Invalid hexadecimal ID parameter");
2315 return 1;
2316 }
2317 }
2318 aliasp[aliasindex].nident = j;
2319
2320 /* This is a security RF transmitter */
2321 aliasp[aliasindex].vtype = RF_SEC;
2322 aliasp[aliasindex].optflags = (MOPT_SECURITY | MOPT_RFIGNORE);
2323
2324 return 0;
2325 }
2326
2327 /*-------------------------------------------------------+
2328 | Called by add_module_options() to add the identity of |
2329 | the X-10 UX17A transceiver to the module. |
2330 +-------------------------------------------------------*/
opt_ux17a(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2331 int opt_ux17a ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2332 {
2333
2334 if ( *ntokens > 0 ) {
2335 store_error_message("This module takes no parameters.");
2336 return 1;
2337 }
2338
2339 /* First byte of UX17A codeword is either 0x82 or 0x83 */
2340 aliasp[aliasindex].nident = 2;
2341 aliasp[aliasindex].ident[0] = 0x82;
2342 aliasp[aliasindex].ident[1] = 0x83;
2343
2344 /* This is an entertainment remote transmitter */
2345 aliasp[aliasindex].vtype = RF_ENT;
2346
2347 return 0;
2348 }
2349
2350 /*-------------------------------------------------------+
2351 | Called by add_module_options() to add the identity of |
2352 | the X-10 UR81A remote to the module. |
2353 +-------------------------------------------------------*/
opt_ur81a(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2354 int opt_ur81a ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2355 {
2356
2357 if ( *ntokens > 0 ) {
2358 store_error_message("This module takes no parameters.");
2359 return 1;
2360 }
2361
2362 /* First byte of UR81A codeword is always 0xEE */
2363 aliasp[aliasindex].nident = 1;
2364 aliasp[aliasindex].ident[0] = 0xEE;
2365
2366 /* This is an entertainment remote transmitter */
2367 aliasp[aliasindex].vtype = RF_ENT;
2368
2369 return 0;
2370 }
2371
2372 /*-------------------------------------------------------+
2373 | Called by add_module_options() to add the IDs for a |
2374 | generic entertainment remote. Valid ID bytes for an |
2375 | entertainment remote have bit 2 (1-8) set. |
2376 +-------------------------------------------------------*/
opt_guru(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2377 int opt_guru ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2378 {
2379 char *sp;
2380 long ident;
2381 int j;
2382
2383 /* Tokens are IDs */
2384 if ( *ntokens < 1 ) {
2385 store_error_message("At least one entertainment ID is needed.");
2386 return 1;
2387 }
2388 if ( *ntokens > NIDENT ) {
2389 store_error_message("Too many parameters on line.");
2390 return 1;
2391 }
2392
2393 for ( j = 0; j < *ntokens; j++ ) {
2394 ident = strtol(tokens[j], &sp, 16);
2395 if ( *sp == '\0' && ident >= 0 && ident <= 0xff && (ident & 0x02) ) {
2396 aliasp[aliasindex].ident[j] = (unsigned short)ident;
2397 }
2398 else {
2399 store_error_message("Invalid hexadecimal entertainment ID parameter");
2400 return 1;
2401 }
2402 }
2403 aliasp[aliasindex].nident = j;
2404
2405 /* This is an entertainment RF transmitter */
2406 aliasp[aliasindex].vtype = RF_ENT;
2407 aliasp[aliasindex].optflags |= MOPT_ENTERTAIN;
2408
2409 return 0;
2410 }
2411
2412
2413
2414
2415 /*-------------------------------------------------------+
2416 | For security remotes with Arm/Disarm buttons |
2417 | Called by add_module_options() to add the RF security |
2418 | ID from the ALIAS line in the config file. |
2419 +-------------------------------------------------------*/
opt_kremote(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2420 int opt_kremote ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2421 {
2422 char *sp;
2423 long ident;
2424 int j;
2425
2426 if ( remote_options(aliasp, aliasindex, tokens, ntokens) != 0 )
2427 return 1;
2428
2429 /* First token is security ID */
2430 if ( *ntokens < 1 ) {
2431 store_error_message("Module ID is needed.");
2432 return 1;
2433 }
2434 if ( *ntokens > NIDENT ) {
2435 store_error_message("Too many parameters on line.");
2436 return 1;
2437 }
2438
2439 for ( j = 0; j < *ntokens; j++ ) {
2440 ident = strtol(tokens[j], &sp, 16);
2441 if ( *sp == '\0' && ident >= 0 && ident <= 0xffff ) {
2442 aliasp[aliasindex].ident[j] = (unsigned short)ident;
2443 }
2444 else {
2445 store_error_message("Invalid hexadecimal ID parameter");
2446 return 1;
2447 }
2448 }
2449 aliasp[aliasindex].nident = j;
2450
2451 /* This is a security RF transmitter */
2452 aliasp[aliasindex].vtype = RF_SEC;
2453 aliasp[aliasindex].optflags |= MOPT_SECURITY;
2454
2455 return 0;
2456 }
2457
2458 /*-------------------------------------------------------+
2459 | Called by add_module_options() to add the RF security |
2460 | ID from the ALIAS line in the config file. |
2461 +-------------------------------------------------------*/
opt_sremote(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2462 int opt_sremote ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2463 {
2464 char *sp;
2465 long ident;
2466 int j;
2467
2468 /* First token is security ID */
2469 if ( *ntokens < 1 ) {
2470 store_error_message("Module ID is needed.");
2471 return 1;
2472 }
2473 if ( *ntokens > NIDENT ) {
2474 store_error_message("Too many parameters on line.");
2475 return 1;
2476 }
2477
2478 for ( j = 0; j < *ntokens; j++ ) {
2479 ident = strtol(tokens[j], &sp, 16);
2480 if ( *sp == '\0' && ident >= 0 && ident <= 0xffff ) {
2481 aliasp[aliasindex].ident[j] = (unsigned short)ident;
2482 }
2483 else {
2484 store_error_message("Invalid hexadecimal ID parameter");
2485 return 1;
2486 }
2487 }
2488 aliasp[aliasindex].nident = j;
2489
2490 /* This is a security RF transmitter */
2491 aliasp[aliasindex].vtype = RF_SEC;
2492 aliasp[aliasindex].optflags |= MOPT_SECURITY;
2493
2494 return 0;
2495 }
2496
2497 /*-------------------------------------------------------+
2498 | Like opt_sremote by also identified as a sensor |
2499 +-------------------------------------------------------*/
opt_svsensor(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2500 int opt_svsensor ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2501 {
2502 if ( opt_sensor(aliasp, aliasindex, tokens, ntokens) != 0 )
2503 return 1;
2504
2505 if ( aliasp[aliasindex].optflags & MOPT_REVERSE ) {
2506 store_error_message("Unsupported module option REVERSE");
2507 return 1;
2508 }
2509
2510 aliasp[aliasindex].optflags &= ~(MOPT_HEARTBEAT | MOPT_LOBAT);
2511
2512 return 0;
2513 }
2514
opt_visonic(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2515 int opt_visonic ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2516 {
2517 char *sp;
2518 long ident;
2519 int j;
2520
2521 /* First token is security ID */
2522 if ( *ntokens < 1 ) {
2523 store_error_message("Module ID is needed.");
2524 return 1;
2525 }
2526 if ( *ntokens > NIDENT ) {
2527 store_error_message("Too many parameters on line.");
2528 return 1;
2529 }
2530
2531 for ( j = 0; j < *ntokens; j++ ) {
2532 ident = strtol(tokens[j], &sp, 16);
2533 if ( *sp == '\0' && ident >= 0 && ident <= 0xffffff ) {
2534 aliasp[aliasindex].ident[j] = ident;
2535 }
2536 else {
2537 store_error_message("Invalid hexadecimal ID parameter");
2538 return 1;
2539 }
2540 }
2541 aliasp[aliasindex].nident = j;
2542
2543 /* This is a security RF transmitter */
2544 aliasp[aliasindex].vtype = RF_VISONIC;
2545 aliasp[aliasindex].optflags |= MOPT_SECURITY;
2546
2547 return 0;
2548 }
2549
2550 /*-------------------------------------------------------+
2551 | Called by add_module_options() to add the RF security |
2552 | sensor options from the ALIAS line in the config file.|
2553 +-------------------------------------------------------*/
opt_sensor(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2554 int opt_sensor ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2555 {
2556 sensor_options(aliasp, aliasindex, tokens, ntokens);
2557
2558 if ( sensor_timeout(aliasp, aliasindex, tokens, ntokens) != 0 )
2559 return 1;
2560
2561 if ( opt_sremote(aliasp, aliasindex, tokens, ntokens) != 0 )
2562 return 1;
2563
2564 if ( single_bmap_unit(aliasp[aliasindex].unitbmap) == 0xff ) {
2565 store_error_message("Multiple unit alias is invalid for sensors.");
2566 return 1;
2567 }
2568
2569 if ( aliasp[aliasindex].nident > 1 ) {
2570 store_error_message("Only one security ID is supported");
2571 return 1;
2572 }
2573
2574 if ( aliasp[aliasindex].optflags & (MOPT_MAIN | MOPT_AUX) ) {
2575 store_error_message("Unsupported module option MAIN or AUX");
2576 return 1;
2577 }
2578
2579 /* This is a sensor with periodic "heartbeat" signals and low battery flag */
2580 aliasp[aliasindex].optflags |= (MOPT_SENSOR | MOPT_HEARTBEAT | MOPT_LOBAT);
2581
2582 return 0;
2583 }
2584
2585 /*-------------------------------------------------------+
2586 | Called by add_module_options() to add the SD90 Smoke |
2587 | Detector IDs from the ALIAS line in the config file. |
2588 +-------------------------------------------------------*/
opt_sd90(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2589 int opt_sd90 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2590 {
2591 unsigned short id0, id1;
2592 unsigned long optflags = 0;
2593
2594 sensor_options(aliasp, aliasindex, tokens, ntokens);
2595
2596 if ( sensor_timeout(aliasp, aliasindex, tokens, ntokens) != 0 )
2597 return 1;
2598
2599 if ( opt_sremote(aliasp, aliasindex, tokens, ntokens) != 0 )
2600 return 1;
2601
2602 if ( single_bmap_unit(aliasp[aliasindex].unitbmap) == 0xff ) {
2603 store_error_message("Multiple unit alias is invalid.");
2604 return 1;
2605 }
2606
2607 if ( aliasp[aliasindex].nident == 2 ) {
2608 id0 = aliasp[aliasindex].ident[0] & 0x00F0;
2609 id1 = aliasp[aliasindex].ident[1] & 0x00F0;
2610 if ( (id0 == 0xC0 && id1 == 0xD0) ||
2611 (id0 == 0xD0 && id1 == 0xC0) ) {
2612 optflags = (MOPT_SENSOR | MOPT_HEARTBEAT | MOPT_LOBAT);
2613 }
2614 else {
2615 store_error_message("Invalid ID value for the SD90");
2616 return 1;
2617 }
2618 }
2619 else if ( aliasp[aliasindex].nident == 1 ) {
2620 id0 = aliasp[aliasindex].ident[0] & 0x00F0;
2621 if ( id0 == 0xD0 ) {
2622 /* Sensor ID */
2623 optflags = (MOPT_SENSOR | MOPT_HEARTBEAT | MOPT_LOBAT);
2624 }
2625 else if ( id0 == 0xC0 ) {
2626 /* Emergency ID */
2627 optflags = 0;
2628 }
2629 else {
2630 store_error_message("Invalid ID value for the SD90");
2631 return 1;
2632 }
2633 }
2634 else {
2635 store_error_message("SD90 module type requires one or two IDs");
2636 return 1;
2637 }
2638
2639 if ( aliasp[aliasindex].optflags & (MOPT_MAIN | MOPT_AUX | MOPT_REVERSE) ) {
2640 store_error_message("Unsupported module option");
2641 return 1;
2642 }
2643
2644 /* This is a sensor */
2645 aliasp[aliasindex].optflags |= /* MOPT_SENSOR | */ optflags;
2646
2647 return 0;
2648 }
2649
2650 /*-------------------------------------------------------+
2651 | Called by add_module_options() for the Marmitek SD10 |
2652 | Smoke Detector which has no "heartbeat". |
2653 +-------------------------------------------------------*/
opt_sd10(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2654 int opt_sd10 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2655 {
2656 char *sp;
2657 long ident;
2658
2659 /* Token is security ID */
2660 if ( single_bmap_unit(aliasp[aliasindex].unitbmap) == 0xff ) {
2661 store_error_message("Multiple unit alias is invalid for sensors.");
2662 return 1;
2663 }
2664
2665 if ( *ntokens < 1 ) {
2666 store_error_message("Module ID is needed.");
2667 return 1;
2668 }
2669 else if ( *ntokens > 1 ) {
2670 store_error_message("Only one security ID is supported.");
2671 return 1;
2672 }
2673
2674 ident = strtol(tokens[0], &sp, 16);
2675 if ( *sp == '\0' && ident >= 0 && ident <= 0xffff ) {
2676 aliasp[aliasindex].ident[0] = (unsigned short)ident;
2677 }
2678 else {
2679 store_error_message("Invalid hexadecimal ID parameter");
2680 return 1;
2681 }
2682
2683 aliasp[aliasindex].nident = 1;
2684
2685 /* This is a security RF transmitter */
2686 aliasp[aliasindex].vtype = RF_SEC;
2687 aliasp[aliasindex].optflags |= MOPT_SECURITY;
2688
2689 return 0;
2690 }
2691
2692 /*-------------------------------------------------------+
2693 | Called by add_module_options() for the BMB-SD18 |
2694 | Smoke Detector |
2695 +-------------------------------------------------------*/
opt_bmb_sd18(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2696 int opt_bmb_sd18 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2697 {
2698 char *sp;
2699 long ident;
2700
2701 if ( sensor_timeout(aliasp, aliasindex, tokens, ntokens) != 0 )
2702 return 1;
2703
2704 /* Token is security ID */
2705 if ( single_bmap_unit(aliasp[aliasindex].unitbmap) == 0xff ) {
2706 store_error_message("Multiple unit alias is invalid for sensors.");
2707 return 1;
2708 }
2709
2710 if ( *ntokens < 1 ) {
2711 store_error_message("Module ID is needed.");
2712 return 1;
2713 }
2714 else if ( *ntokens > 1 ) {
2715 store_error_message("Only one security ID is supported.");
2716 return 1;
2717 }
2718
2719 ident = strtol(tokens[0], &sp, 16);
2720 if ( *sp == '\0' && ident >= 0 && ident <= 0xffff ) {
2721 aliasp[aliasindex].ident[0] = (unsigned short)ident;
2722 }
2723 else {
2724 store_error_message("Invalid hexadecimal ID parameter");
2725 return 1;
2726 }
2727
2728 aliasp[aliasindex].nident = 1;
2729
2730 /* This is a security RF transmitter */
2731 aliasp[aliasindex].vtype = RF_SEC;
2732 aliasp[aliasindex].optflags |= (MOPT_SENSOR | MOPT_SECURITY | MOPT_HEARTBEAT | MOPT_LOBAT);
2733
2734 return 0;
2735 }
2736
2737 /*-------------------------------------------------------+
2738 | Called by add_module_options() for the Marmitek GB10 |
2739 | Glass Break sensor. |
2740 +-------------------------------------------------------*/
opt_gb10(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2741 int opt_gb10 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2742 {
2743 char *sp;
2744 long ident;
2745
2746 if ( sensor_timeout(aliasp, aliasindex, tokens, ntokens) != 0 )
2747 return 1;
2748
2749 /* Token is security ID */
2750 if ( single_bmap_unit(aliasp[aliasindex].unitbmap) == 0xff ) {
2751 store_error_message("Multiple unit alias is invalid for sensors.");
2752 return 1;
2753 }
2754
2755 if ( *ntokens < 1 ) {
2756 store_error_message("Module ID is needed.");
2757 return 1;
2758 }
2759 else if ( *ntokens > 1 ) {
2760 store_error_message("Only one security ID is supported");
2761 return 1;
2762 }
2763
2764 ident = strtol(tokens[0], &sp, 16);
2765 if ( *sp == '\0' && ident >= 0 && ident <= 0xffff ) {
2766 aliasp[aliasindex].ident[0] = (unsigned short)ident;
2767 }
2768 else {
2769 store_error_message("Invalid hexadecimal ID parameter");
2770 return 1;
2771 }
2772
2773 aliasp[aliasindex].nident = 1;
2774
2775 /* This is a security RF transmitter */
2776 aliasp[aliasindex].vtype = RF_SEC;
2777 aliasp[aliasindex].optflags |= ((MOPT_SENSOR | MOPT_SECURITY | MOPT_HEARTBEAT) & ~MOPT_LOBAT);
2778
2779 return 0;
2780 }
2781
2782 /*-------------------------------------------------------+
2783 | Called by add_module_options() for Standard X10 |
2784 | sensors, e.g., MS12,13,14,16 motion detectors. |
2785 +-------------------------------------------------------*/
opt_x10std(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2786 int opt_x10std ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2787 {
2788
2789 aliasp[aliasindex].optflags = 0;
2790
2791 opt_aux(aliasp, aliasindex, tokens, ntokens);
2792
2793 #if 0
2794 aliasp[aliasindex].optflags = 0;
2795
2796 for ( j = 0; j < *ntokens; j++ ) {
2797 strupper(tokens[j]);
2798 if ( strcmp(tokens[j], "TRANSCEIVE") == 0 ) {
2799 aliasp[aliasindex].optflags |= MOPT_TRANSCEIVE;
2800 *tokens[j] = '\0';
2801 count++;
2802 }
2803 else if ( strcmp(tokens[j], "RFFORWARD") == 0 ) {
2804 aliasp[aliasindex].optflags |= MOPT_RFFORWARD;
2805 *tokens[j] = '\0';
2806 count++;
2807 }
2808 else if ( strcmp(tokens[j], "RFIGNORE") == 0 ) {
2809 aliasp[aliasindex].optflags |= MOPT_RFIGNORE;
2810 *tokens[j] = '\0';
2811 count++;
2812 }
2813 else {
2814 store_error_message("Unknown RF option parameter.");
2815 return 1;
2816 }
2817 }
2818
2819 if ( count > 1 ) {
2820 store_error_message("Conflicting RF options.");
2821 return 1;
2822 }
2823
2824 /* Compact to remove "gaps" where tokens were nulled out */
2825
2826 for ( j = 0; j < *ntokens; j++ ) {
2827 if ( *tokens[j] == '\0' ) {
2828 for ( k = j + 1; k < *ntokens; k++ ) {
2829 if ( *tokens[k] != '\0' ) {
2830 tmptok = tokens[j];
2831 tokens[j] = tokens[k];
2832 tokens[k] = tmptok;
2833 *tmptok = '\0';
2834 break;
2835 }
2836 }
2837 }
2838 }
2839
2840 *ntokens -= count;
2841 #endif
2842
2843 aliasp[aliasindex].nident = 0;
2844
2845 /* This is a Standard X10 RF sensor transmitter */
2846 aliasp[aliasindex].vtype = RF_STD;
2847 aliasp[aliasindex].optflags |= MOPT_SENSOR;
2848
2849 return 0;
2850 }
2851
2852 /*-------------------------------------------------------+
2853 | Called by add_module_options() to add the RFXTemp |
2854 | ID from the ALIAS line in the config file. |
2855 +-------------------------------------------------------*/
opt_rfxtemp(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2856 int opt_rfxtemp ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2857 {
2858 sensor_options(aliasp, aliasindex, tokens, ntokens);
2859
2860 if ( sensor_timeout(aliasp, aliasindex, tokens, ntokens) != 0 )
2861 return 1;
2862
2863 if ( opt_sremote(aliasp, aliasindex, tokens, ntokens) != 0 )
2864 return 1;
2865
2866 if ( aliasp[aliasindex].nident > 1 ) {
2867 store_error_message("Only one RFXTemp ID is supported");
2868 return 1;
2869 }
2870
2871 /* This is a sensor with periodic "heartbeat" signals */
2872 aliasp[aliasindex].vtype = RF_XSENSOR;
2873 aliasp[aliasindex].optflags |= (MOPT_RFXSENSOR | MOPT_HEARTBEAT | MOPT_LOBAT);
2874
2875 return 0;
2876 }
2877
2878 /*-------------------------------------------------------+
2879 | Called by add_module_options() to add the RF security |
2880 | sensor options from the ALIAS line in the config file.|
2881 +-------------------------------------------------------*/
opt_ds90(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2882 int opt_ds90 ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2883 {
2884 int check_ds90_ids( unsigned /*short*/ long * );
2885 unsigned short comp_ds90_id( unsigned short, int );
2886
2887 sensor_options(aliasp, aliasindex, tokens, ntokens);
2888
2889 if ( sensor_timeout(aliasp, aliasindex, tokens, ntokens) != 0 )
2890 return 1;
2891
2892 if ( opt_sremote(aliasp, aliasindex, tokens, ntokens) != 0 )
2893 return 1;
2894
2895 if ( (aliasp[aliasindex].optflags & MOPT_MAIN) &&
2896 (aliasp[aliasindex].optflags & MOPT_AUX) ) {
2897 store_error_message("Module options MAIN and AUX are incompatible");
2898 return 1;
2899 }
2900
2901 if ( aliasp[aliasindex].nident > 2 ) {
2902 store_error_message("Too many security IDs for DS90");
2903 return 1;
2904 }
2905 else if ( aliasp[aliasindex].nident == 2 ) {
2906 /* Check main and aux ID and reverse order if necessary */
2907 if ( check_ds90_ids(aliasp[aliasindex].ident) != 0 ) {
2908 store_error_message("DS90 security IDs are incompatible");
2909 return 1;
2910 }
2911 }
2912 else if ( aliasp[aliasindex].optflags & MOPT_MAIN ) {
2913 aliasp[aliasindex].ident[1] =
2914 comp_ds90_id(aliasp[aliasindex].ident[0], COMPUTE_AUX);
2915 aliasp[aliasindex].nident = 2;
2916 }
2917 else if ( aliasp[aliasindex].optflags & MOPT_AUX ) {
2918 aliasp[aliasindex].ident[1] = aliasp[aliasindex].ident[0];
2919 aliasp[aliasindex].ident[0] =
2920 comp_ds90_id(aliasp[aliasindex].ident[1], COMPUTE_MAIN);
2921 aliasp[aliasindex].nident = 2;
2922 }
2923
2924 /* This is a sensor with periodic "heartbeat" signals */
2925 aliasp[aliasindex].optflags |= (MOPT_SENSOR | MOPT_SECURITY | MOPT_HEARTBEAT | MOPT_LOBATUNKN);
2926
2927 return 0;
2928 }
2929
2930
2931 /*-------------------------------------------------------+
2932 | Called by add_module_options() to add the RESUME or |
2933 | ONFULL <level> options from the ALIAS line in the |
2934 | config file. |
2935 +-------------------------------------------------------*/
opt_onlevel(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2936 int opt_onlevel ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
2937 {
2938 int j, type, val, maxval, valoffset;
2939 char *sp;
2940
2941 type = aliasp[aliasindex].modtype;
2942 maxval = modules[type].maxlevel;
2943 valoffset = (modules[type].cflags & PRESET) ? 1 : 0;
2944
2945 for ( j = 0; j < *ntokens; j++ )
2946 strupper(tokens[j]);
2947
2948 j = 0;
2949 while ( *ntokens > 0 ) {
2950 if ( !strcmp(tokens[j], "ONLEVEL") ) {
2951 if ( *ntokens > 1 &&
2952 (!strcmp(tokens[j + 1], "RESUME") ||
2953 !strcmp(tokens[j + 1], "0")) ) {
2954 aliasp[aliasindex].flags |= RESUME;
2955 aliasp[aliasindex].flags &= ~ONFULL;
2956 aliasp[aliasindex].optflags |= MOPT_RESUME;
2957 aliasp[aliasindex].optflags &= ~MOPT_ONFULL;
2958 aliasp[aliasindex].onlevel = maxval;
2959 j += 2;
2960 *ntokens -= 2;
2961 }
2962 else if ( *ntokens > 1 &&
2963 (val = strtol(tokens[j + 1], &sp, 10)) &&
2964 *sp == '\0' && val > 0 &&
2965 val <= (maxval + valoffset) ) {
2966 aliasp[aliasindex].flags &= ~RESUME;
2967 aliasp[aliasindex].flags |= ONFULL;
2968 aliasp[aliasindex].optflags &= ~MOPT_RESUME;
2969 aliasp[aliasindex].optflags |= MOPT_ONFULL;
2970 aliasp[aliasindex].onlevel = val - valoffset;
2971 j += 2;
2972 *ntokens -= 2;
2973 }
2974 else if ( *ntokens > 1 ) {
2975 store_error_message("Invalid ONLEVEL parameter");
2976 return 1;
2977 }
2978 else {
2979 store_error_message("Missing ONLEVEL parameter");
2980 return 1;
2981 }
2982 }
2983 else {
2984 store_error_message("Module option not recognized");
2985 return 1;
2986 }
2987 }
2988 return 0;
2989 }
2990
2991
2992 /*---------------------------------------------------------------------+
2993 | Set TRANSCEIVE, RFFORWARD, or RFIGNORE module options |
2994 +---------------------------------------------------------------------*/
opt_aux(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)2995 int opt_aux ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens)
2996 {
2997 int j, k, count = 0;
2998 char *tmptok;
2999
3000 for ( j = 0; j < *ntokens; j++ ) {
3001 strupper(tokens[j]);
3002 if ( strcmp(tokens[j], "TRANSCEIVE") == 0 ) {
3003 aliasp[aliasindex].optflags |= MOPT_TRANSCEIVE;
3004 *tokens[j] = '\0';
3005 count++;
3006 }
3007 else if ( strcmp(tokens[j], "RFFORWARD") == 0 ) {
3008 aliasp[aliasindex].optflags |= MOPT_RFFORWARD;
3009 *tokens[j] = '\0';
3010 count++;
3011 }
3012 else if ( strcmp(tokens[j], "RFIGNORE") == 0 ) {
3013 aliasp[aliasindex].optflags |= MOPT_RFIGNORE;
3014 *tokens[j] = '\0';
3015 count++;
3016 }
3017 else {
3018 store_error_message("Unknown RF option parameter.");
3019 return 1;
3020 }
3021 }
3022
3023 if ( count == 0 ) {
3024 store_error_message("RF option TRANSCEIVE, RFFORWARD, or RFIGNORE required.");
3025 return 1;
3026 }
3027 else if ( count > 1 ) {
3028 store_error_message("Conflicting RF options.");
3029 return 1;
3030 }
3031
3032 /* Compact to remove "gaps" where tokens were nulled out */
3033
3034 for ( j = 0; j < *ntokens; j++ ) {
3035 if ( *tokens[j] == '\0' ) {
3036 for ( k = j + 1; k < *ntokens; k++ ) {
3037 if ( *tokens[k] != '\0' ) {
3038 tmptok = tokens[j];
3039 tokens[j] = tokens[k];
3040 tokens[k] = tmptok;
3041 *tmptok = '\0';
3042 break;
3043 }
3044 }
3045 }
3046 }
3047
3048 *ntokens -= count;
3049
3050 return 0;
3051 }
3052
3053 /*-------------------------------------------------------+
3054 | Called by add_module_options() to add the identity of |
3055 | a jamming signal from a (older) RFXCOM receiver |
3056 +-------------------------------------------------------*/
opt_jam(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)3057 int opt_jam ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
3058 {
3059
3060 if ( *ntokens > 0 ) {
3061 store_error_message("This module takes no parameters.");
3062 return 1;
3063 }
3064
3065 /* ID is either 0xFF (master) or 0x00 (slave) */
3066 aliasp[aliasindex].nident = 2;
3067 aliasp[aliasindex].ident[0] = 0xFF;
3068 aliasp[aliasindex].ident[1] = 0x00;
3069
3070 /* This is a security remote transmitter */
3071 aliasp[aliasindex].vtype = RF_SEC;
3072
3073 return 0;
3074 }
3075
3076
3077 /*---------------------------------------------------------------------+
3078 | Process received vdata for GB10 Glass Break Sensor |
3079 +---------------------------------------------------------------------*/
fn_gb10(struct xlate_vdata_st * xlate_vdata)3080 int fn_gb10 ( struct xlate_vdata_st *xlate_vdata )
3081 {
3082 unsigned int vdata;
3083
3084 vdata = xlate_vdata->vdata;
3085
3086 if ( vdata & ~(0xF4u) ) {
3087 /* Unknown code */
3088 xlate_vdata->func = VdataFunc;
3089 xlate_vdata->trig = VdataTrig;
3090 xlate_vdata->vflags = 0;
3091 return 0;
3092 }
3093
3094 if ( vdata == 0xF0u ) {
3095 xlate_vdata->func = DuskFunc;
3096 xlate_vdata->trig = DuskTrig;
3097 }
3098 else if ( vdata & 0x80u ) {
3099 xlate_vdata->func = ClearFunc;
3100 xlate_vdata->trig = ClearTrig;
3101 }
3102 else {
3103 xlate_vdata->func = AlertFunc;
3104 xlate_vdata->trig = AlertTrig;
3105 }
3106
3107 #if 0
3108 xlate_vdata->vflags = (vdata & 0x01u) ? SEC_LOBAT : 0;
3109 #endif /* May be needed */
3110
3111 return 0;
3112 }
3113
3114
3115 /*---------------------------------------------------------------------+
3116 | Process received vdata for (Euro) DM10 Motion/Dusk/Dawn sensor |
3117 +---------------------------------------------------------------------*/
fn_dm10(struct xlate_vdata_st * xlate_vdata)3118 int fn_dm10 ( struct xlate_vdata_st *xlate_vdata )
3119 {
3120 unsigned int vdata;
3121
3122 vdata = xlate_vdata->vdata;
3123
3124 if ( vdata == 0xE0u ) {
3125 xlate_vdata->func = AlertFunc;
3126 xlate_vdata->trig = AlertTrig;
3127 }
3128 else if ( vdata == 0xF0 ) {
3129 xlate_vdata->func = DuskFunc;
3130 xlate_vdata->trig = DuskTrig;
3131 }
3132 else if ( vdata == 0xF8 ) {
3133 xlate_vdata->func = DawnFunc;
3134 xlate_vdata->trig = DawnTrig;
3135 }
3136 else {
3137 /* Unknown code */
3138 xlate_vdata->func = VdataFunc;
3139 xlate_vdata->trig = VdataTrig;
3140 }
3141
3142 xlate_vdata->vflags = 0;
3143
3144 #if 0
3145 xlate_vdata->vflags = (vdata & 0x01u) ? SEC_LOBAT : 0;
3146 #endif /* May be needed */
3147
3148 return 0;
3149 }
3150
3151
3152 /*---------------------------------------------------------------------+
3153 | Process received vdata for DS10A Door/Window Sensor |
3154 +---------------------------------------------------------------------*/
fn_ds10a(struct xlate_vdata_st * xlate_vdata)3155 int fn_ds10a ( struct xlate_vdata_st *xlate_vdata )
3156 {
3157 unsigned int vdata;
3158 int polarity;
3159
3160 vdata = xlate_vdata->vdata;
3161 polarity = (xlate_vdata->optflags & MOPT_REVERSE) ? 0 : 1;
3162
3163 xlate_vdata->vflags = 0;
3164
3165 #if 0
3166 if ( vdata == 0xffu ) {
3167 xlate_vdata->func = InactiveFunc;
3168 xlate_vdata->trig = InactiveTrig;
3169 return 0;
3170 }
3171 #endif
3172
3173 if ( vdata & ~(0x85u) ) {
3174 xlate_vdata->func = VdataFunc;
3175 xlate_vdata->trig = VdataTrig;
3176 return 0;
3177 }
3178
3179 if ( vdata & 0x80u ) {
3180 xlate_vdata->func = polarity ? ClearFunc : AlertFunc;
3181 xlate_vdata->trig = polarity ? ClearTrig : AlertTrig;
3182 }
3183 else {
3184 xlate_vdata->func = polarity ? AlertFunc : ClearFunc;
3185 xlate_vdata->trig = polarity ? AlertTrig : ClearTrig;
3186 }
3187
3188 if ( xlate_vdata->func == AlertFunc )
3189 xlate_vdata->vflags |= SEC_FAULT;
3190
3191 xlate_vdata->vflags |= (vdata & 0x04u) ? SEC_MIN : SEC_MAX;
3192 xlate_vdata->vflags |= (vdata & 0x01u) ? SEC_LOBAT : 0;
3193
3194 return 0;
3195 }
3196
3197 /*---------------------------------------------------------------------+
3198 | Process received vdata for ElekHomica DS18 Door/Window Sensor |
3199 +---------------------------------------------------------------------*/
fn_ds18(struct xlate_vdata_st * xlate_vdata)3200 int fn_ds18 ( struct xlate_vdata_st *xlate_vdata )
3201 {
3202 unsigned int vdata;
3203 int polarity;
3204
3205 vdata = xlate_vdata->vdata;
3206 polarity = (xlate_vdata->optflags & MOPT_REVERSE) ? 0 : 1;
3207
3208 xlate_vdata->vflags = 0;
3209
3210 if ( vdata & ~(0x85u) ) {
3211 xlate_vdata->func = VdataFunc;
3212 xlate_vdata->trig = VdataTrig;
3213 return 0;
3214 }
3215
3216 if ( vdata & 0x80 ) {
3217 xlate_vdata->func = polarity ? ClearFunc : AlertFunc;
3218 xlate_vdata->trig = polarity ? ClearTrig : AlertTrig;
3219 }
3220 else {
3221 xlate_vdata->func = polarity ? AlertFunc : ClearFunc;
3222 xlate_vdata->trig = polarity ? AlertTrig : ClearTrig;
3223 }
3224
3225 if ( xlate_vdata->func == AlertFunc )
3226 xlate_vdata->vflags |= SEC_FAULT;
3227
3228 xlate_vdata->vflags |= (vdata & 0x04) ? SEC_MIN : SEC_MAX;
3229 xlate_vdata->vflags |= (vdata & 0x01) ? SEC_LOBAT : 0;
3230
3231 return 0;
3232 }
3233
3234 /*---------------------------------------------------------------------+
3235 | Process received vdata for DS90 Door/Window Sensor |
3236 +---------------------------------------------------------------------*/
fn_ds90(struct xlate_vdata_st * xlate_vdata)3237 int fn_ds90 ( struct xlate_vdata_st *xlate_vdata )
3238 {
3239 unsigned int vdata;
3240 int polarity;
3241 // unsigned short mask;
3242 unsigned long mask;
3243
3244 vdata = xlate_vdata->vdata;
3245 polarity = (xlate_vdata->optflags & MOPT_REVERSE) ? 0 : 1;
3246
3247 mask = configp->securid_mask;
3248
3249 xlate_vdata->func = VdataFunc;
3250 xlate_vdata->trig = VdataTrig;
3251
3252 if ( vdata & ~(0xc5u) ) {
3253 xlate_vdata->func = VdataFunc;
3254 xlate_vdata->trig = VdataTrig;
3255 return 0;
3256 }
3257
3258 if ( (xlate_vdata->optflags & MOPT_MAIN) &&
3259 ((xlate_vdata->ident & mask) == (xlate_vdata->identp[1] & mask)) ) {
3260 /* MAIN specified and signal on AUX, ignore */
3261 return 1;
3262 }
3263 if ( (xlate_vdata->optflags & MOPT_AUX) &&
3264 ((xlate_vdata->ident & mask) == (xlate_vdata->identp[0] & mask)) ) {
3265 /* AUX specified and signal on MAIN, ignore */
3266 return 1;
3267 }
3268
3269
3270 #if 0
3271 if ( !(xlate_vdata->optflags & (MOPT_MAIN | MOPT_AUX)) &&
3272 (xlate_vdata->nident == 2) ) {
3273 /* Neither specified - add appropriate flag */
3274 xlate_vdata->vflags |=
3275 ((xlate_vdata->ident & mask) == (xlate_vdata->identp[0] & mask)) ? SEC_MAIN : SEC_AUX ;
3276 }
3277 #endif
3278
3279
3280 if ( xlate_vdata->nident == 2 ) {
3281 if ( !(xlate_vdata->optflags & (MOPT_MAIN | MOPT_AUX)) ) {
3282 xlate_vdata->vflags |=
3283 ((xlate_vdata->ident & mask) == (xlate_vdata->identp[0] & mask)) ? SEC_MAIN : SEC_AUX ;
3284 }
3285 else if ( xlate_vdata->optflags & MOPT_MAIN ) {
3286 xlate_vdata->vflags |= SEC_MAIN;
3287 }
3288 else {
3289 xlate_vdata->vflags |= SEC_AUX;
3290 }
3291 }
3292
3293
3294 if ( vdata & 0x40 ) {
3295 xlate_vdata->func = TamperFunc;
3296 xlate_vdata->trig = TamperTrig;
3297 // xlate_vdata->vflags |= SEC_TAMPER;
3298 }
3299 else if ( vdata & 0x80 ) {
3300 xlate_vdata->func = polarity ? ClearFunc : AlertFunc;
3301 xlate_vdata->trig = polarity ? ClearTrig : AlertTrig;
3302 }
3303 else {
3304 xlate_vdata->func = polarity ? AlertFunc : ClearFunc;
3305 xlate_vdata->trig = polarity ? AlertTrig : ClearTrig;
3306 }
3307
3308 if ( xlate_vdata->func == AlertFunc )
3309 xlate_vdata->vflags |= SEC_FAULT;
3310
3311 xlate_vdata->vflags |= (vdata & 0x04) ? SEC_MIN : SEC_MAX;
3312 xlate_vdata->vflags |= (vdata & 0x01) ? SEC_LOBAT : 0;
3313
3314 return 0;
3315 }
3316
3317 /*---------------------------------------------------------------------+
3318 | Process received vdata for SD10 Security Smoke Detector |
3319 +---------------------------------------------------------------------*/
fn_sd10(struct xlate_vdata_st * xlate_vdata)3320 int fn_sd10 ( struct xlate_vdata_st *xlate_vdata )
3321 {
3322
3323 unsigned int vdata;
3324
3325 vdata = xlate_vdata->vdata;
3326
3327 xlate_vdata->vflags = 0;
3328
3329 if ( vdata == 0x26u ) {
3330 xlate_vdata->func = AlertFunc;
3331 xlate_vdata->trig = AlertTrig;
3332 }
3333 else {
3334 xlate_vdata->func = VdataFunc;
3335 xlate_vdata->trig = VdataTrig;
3336 }
3337
3338 return 0;
3339 }
3340
3341 /*---------------------------------------------------------------------+
3342 | Process received vdata for BMB-SD18 SD10 Security Smoke Detector |
3343 +---------------------------------------------------------------------*/
fn_bmb_sd18(struct xlate_vdata_st * xlate_vdata)3344 int fn_bmb_sd18 ( struct xlate_vdata_st *xlate_vdata )
3345 {
3346
3347 unsigned int vdata;
3348
3349 vdata = xlate_vdata->vdata;
3350
3351 xlate_vdata->vflags = 0;
3352
3353 xlate_vdata->vflags |= (vdata & 0x01) ? SEC_LOBAT : 0;
3354
3355 switch ( vdata & ~(0x01u) ) {
3356 case 0x26u : /* "R" switch position */
3357 xlate_vdata->func = AlertFunc;
3358 xlate_vdata->trig = AlertTrig;
3359 break;
3360 case 0x66u : /* "R" switch position */
3361 xlate_vdata->func = ClearFunc;
3362 xlate_vdata->trig = ClearTrig;
3363 break;
3364 case 0x04u : /* "S" switch position */
3365 xlate_vdata->func = AlertFunc;
3366 xlate_vdata->trig = AlertTrig;
3367 break;
3368 case 0x80u : /* "S" switch position */
3369 xlate_vdata->func = ClearFunc;
3370 xlate_vdata->trig = ClearTrig;
3371 break;
3372 case 0x44u : /* Heartbeat, either "R" or "S" switch position */
3373 xlate_vdata->func = ClearFunc;
3374 xlate_vdata->trig = ClearTrig;
3375 break;
3376 default : /* Undefined codes */
3377 xlate_vdata->func = VdataFunc;
3378 xlate_vdata->trig = VdataTrig;
3379 break;
3380 }
3381
3382 return 0;
3383 }
3384
3385 /*---------------------------------------------------------------------+
3386 | Process received vdata for KR15A "Big Red Button" |
3387 +---------------------------------------------------------------------*/
fn_kr15a(struct xlate_vdata_st * xlate_vdata)3388 int fn_kr15a ( struct xlate_vdata_st *xlate_vdata )
3389 {
3390
3391 unsigned int vdata;
3392
3393 vdata = xlate_vdata->vdata;
3394
3395 xlate_vdata->vflags = 0;
3396
3397 if ( vdata == 0x03u ) {
3398 xlate_vdata->func = PanicFunc;
3399 xlate_vdata->trig = PanicTrig;
3400 }
3401 else {
3402 xlate_vdata->func = VdataFunc;
3403 xlate_vdata->trig = VdataTrig;
3404 }
3405
3406 return 0;
3407 }
3408
3409 /*---------------------------------------------------------------------+
3410 | Process received vdata for generic X10 security remote |
3411 +---------------------------------------------------------------------*/
fn_svdata(struct xlate_vdata_st * xlate_vdata)3412 int fn_svdata ( struct xlate_vdata_st *xlate_vdata )
3413 {
3414
3415 xlate_vdata->vflags = 0;
3416 xlate_vdata->func = VdataFunc;
3417 xlate_vdata->trig = VdataTrig;
3418
3419 return 0;
3420 }
3421
3422 /*---------------------------------------------------------------------+
3423 | Process received vdata for SD90 Security Smoke Detector |
3424 +---------------------------------------------------------------------*/
fn_sd90(struct xlate_vdata_st * xlate_vdata)3425 int fn_sd90 ( struct xlate_vdata_st *xlate_vdata )
3426 {
3427
3428 unsigned int vdata;
3429
3430 vdata = xlate_vdata->vdata;
3431
3432 xlate_vdata->vflags = 0;
3433
3434
3435 if ( vdata != 0x26u && vdata != 0x27u && (vdata & ~0x85u) ) {
3436 xlate_vdata->func = VdataFunc;
3437 xlate_vdata->trig = VdataTrig;
3438 return 0;
3439 }
3440
3441 xlate_vdata->vflags |= (vdata & 0x01u) ? SEC_LOBAT : 0;
3442
3443 if ( (vdata & 0x26u) == 0x26u ) {
3444 xlate_vdata->func = TestFunc;
3445 xlate_vdata->trig = TestTrig;
3446 }
3447 else if ( (vdata & 0x84u) == 0x84u ) {
3448 xlate_vdata->func = ClearFunc;
3449 xlate_vdata->trig = ClearTrig;
3450 }
3451 else {
3452 xlate_vdata->func = AlertFunc;
3453 xlate_vdata->trig = AlertTrig;
3454 }
3455
3456 return 0;
3457 }
3458
3459 /*---------------------------------------------------------------------+
3460 | Process received vdata for MS90 Security Motion Sensor |
3461 +---------------------------------------------------------------------*/
fn_ms90(struct xlate_vdata_st * xlate_vdata)3462 int fn_ms90 ( struct xlate_vdata_st *xlate_vdata )
3463 {
3464
3465 unsigned int vdata;
3466
3467 vdata = xlate_vdata->vdata;
3468
3469 xlate_vdata->vflags = 0;
3470
3471
3472 if ( (vdata & 0x0Cu) != 0x0Cu || vdata & ~(0xCDu) ) {
3473 xlate_vdata->func = VdataFunc;
3474 xlate_vdata->trig = VdataTrig;
3475 return 0;
3476 }
3477
3478 xlate_vdata->vflags |= (vdata & 0x01u) ? SEC_LOBAT : 0;
3479 // xlate_vdata->vflags |= (vdata & 0x40u) ? SEC_TAMPER : 0;
3480
3481 if ( vdata & 0x40u ) {
3482 xlate_vdata->func = TamperFunc;
3483 xlate_vdata->trig = TamperTrig;
3484 }
3485 else if ( vdata & 0x80u ) {
3486 xlate_vdata->func = ClearFunc;
3487 xlate_vdata->trig = ClearTrig;
3488 }
3489 else {
3490 xlate_vdata->func = AlertFunc;
3491 xlate_vdata->trig = AlertTrig;
3492 }
3493
3494 return 0;
3495 }
3496
3497 /*---------------------------------------------------------------------+
3498 | Process received vdata for MS10A Security Motion Sensor |
3499 +---------------------------------------------------------------------*/
fn_ms10a(struct xlate_vdata_st * xlate_vdata)3500 int fn_ms10a ( struct xlate_vdata_st *xlate_vdata )
3501 {
3502
3503 unsigned int vdata;
3504
3505 vdata = xlate_vdata->vdata;
3506
3507 xlate_vdata->vflags = 0;
3508
3509
3510 if ( (vdata & 0x0cu) != 0x0cu || vdata & ~(0x8du) ) {
3511 xlate_vdata->func = VdataFunc;
3512 xlate_vdata->trig = VdataTrig;
3513 return 0;
3514 }
3515
3516 xlate_vdata->vflags |= (vdata & 0x01u) ? SEC_LOBAT : 0;
3517
3518 if ( vdata & 0x80u ) {
3519 xlate_vdata->func = ClearFunc;
3520 xlate_vdata->trig = ClearTrig;
3521 }
3522 else {
3523 xlate_vdata->func = AlertFunc;
3524 xlate_vdata->trig = AlertTrig;
3525 }
3526
3527 return 0;
3528 }
3529
3530 /*---------------------------------------------------------------------+
3531 | Process received vdata for SH624 Security Remote Control |
3532 +---------------------------------------------------------------------*/
fn_sh624(struct xlate_vdata_st * xlate_vdata)3533 int fn_sh624 ( struct xlate_vdata_st *xlate_vdata )
3534 {
3535
3536 unsigned int vdata;
3537
3538 vdata = xlate_vdata->vdata;
3539
3540 xlate_vdata->vflags = 0;
3541
3542
3543 if ( !(vdata & 0x02) || (vdata & 0x11) ) {
3544 xlate_vdata->func = VdataFunc;
3545 xlate_vdata->trig = VdataTrig;
3546 return 0;
3547 }
3548
3549 if ( vdata & 0x20 ) {
3550 xlate_vdata->func = PanicFunc;
3551 xlate_vdata->trig = PanicTrig;
3552 }
3553 else if ( vdata & 0x40 ) {
3554 if ( vdata & 0x80 ) {
3555 xlate_vdata->func = SecLightsOffFunc;
3556 xlate_vdata->trig = SecLightsOffTrig;
3557 }
3558 else {
3559 xlate_vdata->func = SecLightsOnFunc;
3560 xlate_vdata->trig = SecLightsOnTrig;
3561 }
3562 }
3563 else {
3564 if ( vdata & 0x80 ) {
3565 xlate_vdata->func = DisarmFunc;
3566 xlate_vdata->trig = DisarmTrig;
3567 }
3568 else {
3569 xlate_vdata->func = ArmFunc;
3570 xlate_vdata->trig = ArmTrig;
3571 xlate_vdata->vflags |= ((vdata & 0x08) ? SEC_HOME : SEC_AWAY);
3572 xlate_vdata->vflags |= ((vdata & 0x04) ? SEC_MIN : SEC_MAX);
3573 }
3574 }
3575 return 0;
3576 }
3577
3578 /*---------------------------------------------------------------------+
3579 | Process received vdata for KR10A Security Keychain Remote Control |
3580 +---------------------------------------------------------------------*/
fn_kr10a(struct xlate_vdata_st * xlate_vdata)3581 int fn_kr10a ( struct xlate_vdata_st *xlate_vdata )
3582 {
3583
3584 unsigned int vdata;
3585
3586 vdata = xlate_vdata->vdata;
3587
3588 xlate_vdata->vflags = 0;
3589
3590
3591 if ( (vdata & 0x0f) != 0x06 || (vdata & 0x11) ) {
3592 xlate_vdata->func = VdataFunc;
3593 xlate_vdata->trig = VdataTrig;
3594 return 0;
3595 }
3596
3597 if ( vdata & 0x20 ) {
3598 xlate_vdata->func = PanicFunc;
3599 xlate_vdata->trig = PanicTrig;
3600 }
3601 else if ( vdata & 0x40 ) {
3602 if ( vdata & 0x80 ) {
3603 xlate_vdata->func = SecLightsOffFunc;
3604 xlate_vdata->trig = SecLightsOffTrig;
3605 }
3606 else {
3607 xlate_vdata->func = SecLightsOnFunc;
3608 xlate_vdata->trig = SecLightsOnTrig;
3609 }
3610 }
3611 else {
3612 if ( vdata & 0x80 ) {
3613 if ( xlate_vdata->optflags2 & MOPT2_DUMMY ) {
3614 xlate_vdata->func = ClearFunc;
3615 xlate_vdata->trig = ClearTrig;
3616 }
3617 else {
3618 xlate_vdata->func = DisarmFunc;
3619 xlate_vdata->trig = DisarmTrig;
3620 }
3621 }
3622 else {
3623 if ( xlate_vdata->optflags2 & MOPT2_DUMMY ) {
3624 xlate_vdata->func = AlertFunc;
3625 xlate_vdata->trig = AlertTrig;
3626 }
3627 else {
3628 xlate_vdata->func = ArmFunc;
3629 xlate_vdata->trig = ArmTrig;
3630 xlate_vdata->vflags |= (xlate_vdata->optflags2 & MOPT2_SWHOME) ? SEC_HOME : SEC_AWAY;
3631 xlate_vdata->vflags |= (xlate_vdata->optflags2 & MOPT2_SWMAX) ? SEC_MAX : SEC_MIN;
3632 }
3633 }
3634 }
3635 return 0;
3636 }
3637
3638 /*---------------------------------------------------------------------+
3639 | Process received vdata for Marmitek KR18 Security Keychain Remote |
3640 +---------------------------------------------------------------------*/
fn_kr18(struct xlate_vdata_st * xlate_vdata)3641 int fn_kr18 ( struct xlate_vdata_st *xlate_vdata )
3642 {
3643 xlate_vdata->vflags = 0;
3644
3645 switch ( xlate_vdata-> vdata ) {
3646 case 0x26 :
3647 xlate_vdata->func = PanicFunc;
3648 xlate_vdata->trig = PanicTrig;
3649 break;
3650 case 0x06 :
3651 if ( xlate_vdata->optflags2 & MOPT2_DUMMY ) {
3652 xlate_vdata->func = AlertFunc;
3653 xlate_vdata->trig = AlertTrig;
3654 }
3655 else {
3656 xlate_vdata->func = ArmFunc;
3657 xlate_vdata->trig = ArmTrig;
3658 xlate_vdata->vflags |= (xlate_vdata->optflags2 & MOPT2_SWHOME) ? SEC_HOME : SEC_AWAY;
3659 xlate_vdata->vflags |= (xlate_vdata->optflags2 & MOPT2_SWMAX) ? SEC_MAX : SEC_MIN;
3660 }
3661 break;
3662 case 0x86 :
3663 if ( xlate_vdata->optflags2 & MOPT2_DUMMY ) {
3664 xlate_vdata->func = ClearFunc;
3665 xlate_vdata->trig = ClearTrig;
3666 }
3667 else {
3668 xlate_vdata->func = DisarmFunc;
3669 xlate_vdata->trig = DisarmTrig;
3670 }
3671 break;
3672 case 0x42 :
3673 xlate_vdata->func = AkeyOnFunc;
3674 xlate_vdata->trig = AkeyOnTrig;
3675 break;
3676 case 0xC2 :
3677 xlate_vdata->func = AkeyOffFunc;
3678 xlate_vdata->trig = AkeyOffTrig;
3679 break;
3680 case 0x46 :
3681 xlate_vdata->func = BkeyOnFunc;
3682 xlate_vdata->trig = BkeyOnTrig;
3683 break;
3684 case 0xC6 :
3685 xlate_vdata->func = BkeyOffFunc;
3686 xlate_vdata->trig = BkeyOffTrig;
3687 break;
3688 default :
3689 xlate_vdata->func = VdataFunc;
3690 xlate_vdata->trig = VdataTrig;
3691 break;
3692 }
3693 return 0;
3694 }
3695
3696 /*---------------------------------------------------------------------+
3697 | Process received vdata for UR81A Entertainment Remote Control |
3698 +---------------------------------------------------------------------*/
fn_ur81a(struct xlate_vdata_st * xlate_vdata)3699 int fn_ur81a ( struct xlate_vdata_st *xlate_vdata )
3700 {
3701
3702 xlate_vdata->vflags = 0;
3703 xlate_vdata->func = VdataFunc;
3704 xlate_vdata->trig = VdataTrig;
3705
3706 return 0;
3707 }
3708
3709 /*---------------------------------------------------------------------+
3710 | Process received vdata for General Universal Remote Unit (GURU) |
3711 +---------------------------------------------------------------------*/
fn_guru(struct xlate_vdata_st * xlate_vdata)3712 int fn_guru ( struct xlate_vdata_st *xlate_vdata )
3713 {
3714
3715 xlate_vdata->vflags = 0;
3716 xlate_vdata->func = VdataFunc;
3717 xlate_vdata->trig = VdataTrig;
3718
3719 return 0;
3720 }
3721
3722 /*---------------------------------------------------------------------+
3723 | Process received vdata for RFXSensor |
3724 +---------------------------------------------------------------------*/
fn_rfxsensor(struct xlate_vdata_st * xlate_vdata)3725 int fn_rfxsensor ( struct xlate_vdata_st *xlate_vdata )
3726 {
3727
3728 if ( (xlate_vdata->lobyte) & 0x10u && xlate_vdata->hibyte != 0x02u ) {
3729 xlate_vdata->func = RFXOtherFunc;
3730 xlate_vdata->trig = RFXOtherTrig;
3731 return 0;
3732 }
3733
3734 switch ( xlate_vdata->ident % 0x04u ) {
3735 case 0 :
3736 xlate_vdata->func = RFXTempFunc;
3737 xlate_vdata->trig = RFXTempTrig;
3738 break;
3739 case 1 :
3740 if ( xlate_vdata->optflags & MOPT_RFXRH ) {
3741 xlate_vdata->func = RFXHumidFunc;
3742 xlate_vdata->trig = RFXHumidTrig;
3743 }
3744 else if ( xlate_vdata->optflags & MOPT_RFXBP ) {
3745 xlate_vdata->func = RFXPressFunc;
3746 xlate_vdata->trig = RFXPressTrig;
3747 }
3748 else if ( xlate_vdata->optflags & MOPT_RFXPOT ) {
3749 xlate_vdata->func = RFXPotFunc;
3750 xlate_vdata->trig = RFXPotTrig;
3751 }
3752 else {
3753 xlate_vdata->func = RFXVadFunc;
3754 xlate_vdata->trig = RFXVadTrig;
3755 }
3756 break;
3757 case 2 :
3758 if ( xlate_vdata->lobyte & 0x10u ) {
3759 xlate_vdata->func = RFXLoBatFunc;
3760 xlate_vdata->trig = RFXLoBatTrig;
3761 }
3762 else {
3763 xlate_vdata->func = RFXVsFunc;
3764 xlate_vdata->trig = RFXVsTrig;
3765 }
3766 break;
3767 default :
3768 break;
3769 }
3770
3771 return 0;
3772 }
3773
3774 /*---------------------------------------------------------------------+
3775 | Process received vdata for RFXMeter Pulse |
3776 +---------------------------------------------------------------------*/
fn_rfxpulse(struct xlate_vdata_st * xlate_vdata)3777 int fn_rfxpulse ( struct xlate_vdata_st *xlate_vdata )
3778 {
3779 xlate_vdata->vflags = 0;
3780 xlate_vdata->func = RFXPulseFunc;
3781 xlate_vdata->trig = RFXPulseTrig;
3782
3783 return 0;
3784 }
3785
3786 /*---------------------------------------------------------------------+
3787 | Process received vdata for RFXMeter Counter |
3788 +---------------------------------------------------------------------*/
fn_rfxcount(struct xlate_vdata_st * xlate_vdata)3789 int fn_rfxcount ( struct xlate_vdata_st *xlate_vdata )
3790 {
3791 xlate_vdata->vflags = 0;
3792 xlate_vdata->func = RFXCountFunc;
3793 xlate_vdata->trig = RFXCountTrig;
3794
3795 return 0;
3796 }
3797
3798 /*---------------------------------------------------------------------+
3799 | Process received vdata for RFXMeter Power |
3800 +---------------------------------------------------------------------*/
fn_rfxpower(struct xlate_vdata_st * xlate_vdata)3801 int fn_rfxpower ( struct xlate_vdata_st *xlate_vdata )
3802 {
3803 xlate_vdata->vflags = 0;
3804 xlate_vdata->func = RFXPowerFunc;
3805 xlate_vdata->trig = RFXPowerTrig;
3806
3807 return 0;
3808 }
3809
3810 /*---------------------------------------------------------------------+
3811 | Process received vdata for RFXMeter Water |
3812 +---------------------------------------------------------------------*/
fn_rfxwater(struct xlate_vdata_st * xlate_vdata)3813 int fn_rfxwater ( struct xlate_vdata_st *xlate_vdata )
3814 {
3815 xlate_vdata->vflags = 0;
3816 xlate_vdata->func = RFXWaterFunc;
3817 xlate_vdata->trig = RFXWaterTrig;
3818
3819 return 0;
3820 }
3821
3822 /*---------------------------------------------------------------------+
3823 | Process received vdata for RFXMeter Pulse |
3824 +---------------------------------------------------------------------*/
fn_rfxgas(struct xlate_vdata_st * xlate_vdata)3825 int fn_rfxgas ( struct xlate_vdata_st *xlate_vdata )
3826 {
3827 xlate_vdata->vflags = 0;
3828 xlate_vdata->func = RFXGasFunc;
3829 xlate_vdata->trig = RFXGasTrig;
3830
3831 return 0;
3832 }
3833
fn_visonic(struct xlate_vdata_st * xlate_vdata)3834 int fn_visonic ( struct xlate_vdata_st *xlate_vdata )
3835 {
3836
3837 xlate_vdata->func = VdataFunc;
3838 xlate_vdata->trig = VdataTrig;
3839 xlate_vdata->vflags = 0;
3840
3841 return 0;
3842 }
3843
3844 /*---------------------------------------------------------------------+
3845 | Check the compatibility and order of DS90 IDs. After bit reversal, |
3846 | each byte of the aux ID must be the corresponding byte of the |
3847 | primary ID + 1. |
3848 | Reverse the order if necessary to get compatibility. |
3849 | Return 0 if OK or 1 if the IDs don't have a valid relationship. |
3850 +---------------------------------------------------------------------*/
check_ds90_ids(unsigned long * identp)3851 int check_ds90_ids( unsigned /*short*/ long *identp )
3852 {
3853 unsigned short mid, mid1, midlo, midhi, mask, temp;
3854 unsigned short aid, aid1, aidlo, aidhi;
3855
3856 mask = (identp[0] > 0xffu || identp[1] > 0xffu) ? 0xffffu : 0x00ffu;
3857
3858 midlo = rev_byte_bits( identp[0] & 0x00ffu);
3859 midhi = rev_byte_bits((identp[0] & 0xff00u & mask) >> 8) << 8;
3860 aidlo = rev_byte_bits( identp[1] & 0x00ffu);
3861 aidhi = rev_byte_bits((identp[1] & 0xff00u & mask) >> 8) << 8;
3862
3863 mid = midhi | midlo;
3864 aid = aidhi | aidlo;
3865
3866 mid1 = (((midhi + 0x0100u) & 0xff00u) | ((midlo + 0x0001u) & 0x00ffu)) & mask;
3867 aid1 = (((aidhi + 0x0100u) & 0xff00u) | ((aidlo + 0x0001u) & 0x00ffu)) & mask;
3868
3869 if ( aid == mid1 ) {
3870 /* Order is OK */
3871 return 0;
3872 }
3873
3874 if ( aid1 == mid ) {
3875 /* Reverse the order */
3876 temp = identp[0];
3877 identp[0] = identp[1];
3878 identp[1] = temp;
3879 return 0;
3880 }
3881
3882 /* Invalid relationship */
3883 return 1;
3884 }
3885
3886 /*---------------------------------------------------------------------+
3887 | Determine the companion ID for a DS90 ID. If func = COMPUTE_AUX, |
3888 | find the aux ID for the argument main ID; otherwise find the main |
3889 | ID for the argument aux ID. |
3890 +---------------------------------------------------------------------*/
comp_ds90_id(unsigned short ident,int func)3891 unsigned short comp_ds90_id ( unsigned short ident, int func )
3892 {
3893 unsigned short mask, newid;
3894 unsigned char idlo, idhi, id1lo, id1hi;
3895
3896 mask = (ident > 0xffu) ? 0xffffu : 0x00ffu;
3897
3898 idlo = rev_byte_bits(ident & 0x00ffu);
3899 idhi = rev_byte_bits((ident & 0xff00u & mask) >> 8);
3900
3901 ident = rev_byte_bits(ident & 0xffu);
3902
3903 if ( func == COMPUTE_AUX ) {
3904 /* Get aux corresponding to main */
3905 id1hi = ((idhi + 0x0001u) & 0x00ffu) & (mask >> 8);
3906 id1lo = ((idlo + 0x0001u) & 0x00ffu);
3907 }
3908 else {
3909 /* Get main corresponding to aux */
3910 id1hi = ((idhi - 0x0001u) & 0x00ffu) & (mask >> 8);
3911 id1lo = ((idlo - 0x0001u) & 0x00ffu);
3912 }
3913 newid = (rev_byte_bits(id1hi) << 8) | rev_byte_bits(id1lo);
3914 return newid;
3915 }
3916
3917
cmp_modules(const void * m1,const void * m2)3918 int cmp_modules ( const void *m1, const void *m2 )
3919 {
3920 struct modules_st *one, *two;
3921
3922 one = (struct modules_st *)m1; two = (struct modules_st *)m2;
3923
3924 return strcmp(one->label, two->label);
3925 }
3926
c_modlist(int argc,char * argv[])3927 int c_modlist ( int argc, char *argv[] )
3928 {
3929 int j;
3930 qsort(modules, ntypes, sizeof(struct modules_st), cmp_modules);
3931
3932 for ( j = 0; j < ntypes; j++ )
3933 printf("%s\n", modules[j].label);
3934 printf("\n");
3935
3936 return 0;
3937 }
3938
3939
3940 /*---------------------------------------------------------------------+
3941 | Get a temperature parameter from the tokenized ALIAS directive for |
3942 | a sensor. |
3943 +---------------------------------------------------------------------*/
temp_parm(char ** tokens,int * ntokens,char * tparmname,char * tscale,int * tflag,double * tvalue)3944 int temp_parm ( char **tokens, int *ntokens, char *tparmname, char *tscale,
3945 int *tflag, double *tvalue )
3946 {
3947 char msg[80];
3948 int j, k, count = 0;
3949 char *sp, *tmptok;
3950
3951 *tflag = 0;
3952
3953 j = 0;
3954 while ( j < *ntokens ) {
3955 strupper(tokens[j]);
3956 if ( strcmp(tokens[j], tparmname) == 0 ) {
3957 *tokens[j] = '\0';
3958 j++;
3959 if ( j >= *ntokens ) {
3960 sprintf(msg, "Missing %s value.", tparmname);
3961 store_error_message(msg);
3962 return 1;
3963 }
3964 strupper(tokens[j]);
3965 *tvalue = strtod(tokens[j], &sp);
3966 if ( strchr("CFKR", *sp) && strchr(" \t\n\r", *(sp + 1)) ) {
3967 *tscale = *sp;
3968 }
3969 else if ( !strchr(" \t\n\r", *sp) ) {
3970 sprintf(msg, "Invalid %s value or scale.", tparmname);
3971 store_error_message(msg);
3972 return 1;
3973 }
3974 *tokens[j] = '\0';
3975 *tflag = 1;
3976 count += 2;
3977 }
3978 j++;
3979 }
3980
3981 if ( count == 0 )
3982 return 0;
3983
3984 /* Compact to remove "gaps" where tokens were nulled out */
3985
3986 for ( j = 0; j < *ntokens; j++ ) {
3987 if ( *tokens[j] == '\0' ) {
3988 for ( k = j + 1; k < *ntokens; k++ ) {
3989 if ( *tokens[k] != '\0' ) {
3990 tmptok = tokens[j];
3991 tokens[j] = tokens[k];
3992 tokens[k] = tmptok;
3993 *tmptok = '\0';
3994 break;
3995 }
3996 }
3997 }
3998 }
3999 *ntokens -= count;
4000
4001 return 0;
4002 }
4003
4004 /*---------------------------------------------------------------------+
4005 | Get a relative humidity parameter from the tokenized ALIAS |
4006 | directive for a sensor. |
4007 +---------------------------------------------------------------------*/
rh_parm(char ** tokens,int * ntokens,char * rhparmname,char * rhscale,int * rhflag,double * rhvalue)4008 int rh_parm ( char **tokens, int *ntokens, char *rhparmname, char *rhscale,
4009 int *rhflag, double *rhvalue )
4010 {
4011 char msg[80];
4012 int j, k, count = 0;
4013 char *sp, *tmptok;
4014
4015 *rhflag = 0;
4016
4017 j = 0;
4018 while ( j < *ntokens ) {
4019 strupper(tokens[j]);
4020 if ( strcmp(tokens[j], rhparmname) == 0 ) {
4021 *tokens[j] = '\0';
4022 j++;
4023 if ( j >= *ntokens ) {
4024 sprintf(msg, "Missing %s value.", rhparmname);
4025 store_error_message(msg);
4026 return 1;
4027 }
4028 strupper(tokens[j]);
4029 *rhvalue = strtod(tokens[j], &sp);
4030 *rhscale = '%';
4031 if ( !strchr(" %\t\n\r", *sp) ) {
4032 sprintf(msg, "Invalid %s value.", rhparmname);
4033 store_error_message(msg);
4034 return 1;
4035 }
4036 *tokens[j] = '\0';
4037 *rhflag = 1;
4038 count += 2;
4039 }
4040 j++;
4041 }
4042
4043 if ( count == 0 )
4044 return 0;
4045
4046 /* Compact to remove "gaps" where tokens were nulled out */
4047
4048 for ( j = 0; j < *ntokens; j++ ) {
4049 if ( *tokens[j] == '\0' ) {
4050 for ( k = j + 1; k < *ntokens; k++ ) {
4051 if ( *tokens[k] != '\0' ) {
4052 tmptok = tokens[j];
4053 tokens[j] = tokens[k];
4054 tokens[k] = tmptok;
4055 *tmptok = '\0';
4056 break;
4057 }
4058 }
4059 }
4060 }
4061 *ntokens -= count;
4062
4063 return 0;
4064 }
4065
4066 /*---------------------------------------------------------------------+
4067 | Get a barometric pressure parameter from the tokenized ALIAS |
4068 | directive for a sensor. |
4069 +---------------------------------------------------------------------*/
bp_parm(char ** tokens,int * ntokens,char * bpparmname,char * bpunits,int * bpflag,double * bpvalue)4070 int bp_parm ( char **tokens, int *ntokens, char *bpparmname, char *bpunits,
4071 int *bpflag, double *bpvalue )
4072 {
4073 char msg[80];
4074 int j, k, count = 0;
4075 char *sp, *tmptok;
4076
4077 *bpflag = 0;
4078
4079 j = 0;
4080 while ( j < *ntokens ) {
4081 strupper(tokens[j]);
4082 if ( strcmp(tokens[j], bpparmname) == 0 ) {
4083 *tokens[j] = '\0';
4084 j++;
4085 if ( j >= *ntokens ) {
4086 sprintf(msg, "Missing %s value.", bpparmname);
4087 store_error_message(msg);
4088 return 1;
4089 }
4090 strupper(tokens[j]);
4091 *bpvalue = strtod(tokens[j], &sp);
4092 if ( strchr(" \t\n\r", *sp) )
4093 *bpunits = '\0';
4094 else
4095 strncpy(bpunits, sp, NAME_LEN);
4096
4097 *tokens[j] = '\0';
4098 *bpflag = 1;
4099 count += 2;
4100 }
4101 j++;
4102 }
4103
4104 if ( count == 0 )
4105 return 0;
4106
4107 /* Compact to remove "gaps" where tokens were nulled out */
4108
4109 for ( j = 0; j < *ntokens; j++ ) {
4110 if ( *tokens[j] == '\0' ) {
4111 for ( k = j + 1; k < *ntokens; k++ ) {
4112 if ( *tokens[k] != '\0' ) {
4113 tmptok = tokens[j];
4114 tokens[j] = tokens[k];
4115 tokens[k] = tmptok;
4116 *tmptok = '\0';
4117 break;
4118 }
4119 }
4120 }
4121 }
4122 *ntokens -= count;
4123
4124 return 0;
4125 }
4126
4127 /*---------------------------------------------------------------------+
4128 | Get inactive_timeout parameter from the tokenized ALIAS directive |
4129 | for a sensor. |
4130 +---------------------------------------------------------------------*/
timeout_parm(char ** tokens,int * ntokens,char * parmname,int * toflag,long * timeout)4131 int timeout_parm ( char **tokens, int *ntokens, char *parmname,
4132 int *toflag, long *timeout )
4133 {
4134 char msg[80];
4135 int j, k, count = 0;
4136 char *totok;
4137
4138 *toflag = 0;
4139
4140 j = 0;
4141 while ( j < *ntokens ) {
4142 strupper(tokens[j]);
4143 if ( strcmp(tokens[j], parmname) == 0 ) {
4144 *tokens[j] = '\0';
4145 j++;
4146 if ( j >= *ntokens ) {
4147 sprintf(msg, "Missing %s hh:mm:ss value.", parmname);
4148 store_error_message(msg);
4149 return 1;
4150 }
4151 if ( (*timeout = parse_hhmmss(tokens[j], 3)) < 0 || *timeout > 86400L ) {
4152 sprintf(msg, "Invalid %s timeout '%s'.", parmname, tokens[j]);
4153 store_error_message(msg);
4154 return 1;
4155 }
4156
4157 *tokens[j] = '\0';
4158 *toflag = 1;
4159 count += 2;
4160 }
4161 j++;
4162 }
4163
4164 if ( count == 0 )
4165 return 0;
4166
4167 /* Compact to remove "gaps" where tokens were nulled out */
4168
4169 for ( j = 0; j < *ntokens; j++ ) {
4170 if ( *tokens[j] == '\0' ) {
4171 for ( k = j + 1; k < *ntokens; k++ ) {
4172 if ( *tokens[k] != '\0' ) {
4173 totok = tokens[j];
4174 tokens[j] = tokens[k];
4175 tokens[k] = totok;
4176 *totok = '\0';
4177 break;
4178 }
4179 }
4180 }
4181 }
4182 *ntokens -= count;
4183
4184 return 0;
4185 }
4186
4187
sensor_timeout(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)4188 int sensor_timeout ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
4189 {
4190 long timeout;
4191 int toflag;
4192
4193 int timeout_parm ( char **, int *, char *, int *, long * );
4194
4195 if ( timeout_parm(tokens, ntokens, "IATO", &toflag, &timeout) != 0 )
4196 return 1;
4197
4198 if ( toflag ) {
4199 aliasp[aliasindex].optflags2 |= MOPT2_IATO;
4200 aliasp[aliasindex].hb_timeout = timeout;
4201 }
4202
4203 return 0;
4204 }
4205
4206
4207
4208 /*-------------------------------------------------------+
4209 | Called by add_module_options() to add the KAKU |
4210 | sensor options from the ALIAS line in the config file.|
4211 +-------------------------------------------------------*/
opt_kaku_orig(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)4212 int opt_kaku_orig ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
4213 {
4214 long ident;
4215 int key, grp;
4216 char *sp;
4217
4218 if ( *ntokens < 2 || *ntokens > 3 ) {
4219 store_error_message("Unknown parameters");
4220 return 1;
4221 }
4222
4223 if ( single_bmap_unit(aliasp[aliasindex].unitbmap) == 0xff ) {
4224 store_error_message("Multiple unit alias is invalid for sensors.");
4225 return 1;
4226 }
4227
4228 ident = strtol(tokens[0], &sp, 16);
4229 if ( *sp == '\0' && ident >= 0 ) {
4230 aliasp[aliasindex].ident[0] = ident;
4231 aliasp[aliasindex].nident = 1;
4232 }
4233 else {
4234 store_error_message("Invalid hexadecimal KAKU ID parameter");
4235 return 1;
4236 }
4237
4238 key = strtol(tokens[1], &sp, 10);
4239 if ( *sp == '\0' && key > 0 && key <= 16 ) {
4240 aliasp[aliasindex].kaku_keymap[0] = 1 << (key - 1);
4241 }
4242 else {
4243 store_error_message("Invalid KAKU key parameter");
4244 return 1;
4245 }
4246
4247 if ( *ntokens == 3 ) {
4248 grp = toupper((int)((unsigned char)(*tokens[2])));
4249 if ( strlen(tokens[2]) == 1 && grp >= 'A' && grp <= 'P' ) {
4250 aliasp[aliasindex].kaku_grpmap[0] = 1 << (grp - 'A');
4251 }
4252 else {
4253 store_error_message("Invalid KAKU group parameter");
4254 return 1;
4255 }
4256 }
4257
4258 aliasp[aliasindex].vtype = RF_KAKU;
4259
4260 aliasp[aliasindex].optflags = MOPT_KAKU;
4261
4262 return 0;
4263 }
4264
4265 /*-------------------------------------------------------+
4266 | Called by add_module_options() to add the KAKU |
4267 | sensor options from the ALIAS line in the config file.|
4268 +-------------------------------------------------------*/
opt_kaku(ALIAS * aliasp,int aliasindex,char ** tokens,int * ntokens)4269 int opt_kaku ( ALIAS *aliasp, int aliasindex, char **tokens, int *ntokens )
4270 {
4271 long ident;
4272 int nident, key, grp;
4273 int j;
4274 char *sp;
4275
4276 if ( *ntokens < 2 ) {
4277 store_error_message("Too few parameters");
4278 return 1;
4279 }
4280 else if ( *ntokens > 12 ) {
4281 store_error_message("Too many parameters");
4282 return 1;
4283 }
4284 else if ( ((*ntokens) % 2) != 0 ) {
4285 store_error_message("Parameter syntax: <ID> <Key|Grp> [<ID> <Key|Grp> [...]]");
4286 return 1;
4287 }
4288
4289
4290 if ( single_bmap_unit(aliasp[aliasindex].unitbmap) == 0xff ) {
4291 store_error_message("Multiple unit alias is invalid for sensors.");
4292 return 1;
4293 }
4294
4295 nident = 0;
4296 for ( j = 0; j < *ntokens; j += 2 ) {
4297 ident = strtol(tokens[j], &sp, 16);
4298 if ( strchr(" \t", *sp) && ident >= 0 ) {
4299 aliasp[aliasindex].ident[nident] = ident;
4300 }
4301 else {
4302 store_error_message("Invalid hexadecimal KAKU ID parameter");
4303 return 1;
4304 }
4305
4306 if ( isdigit((int)((unsigned char)(*tokens[j+1]))) ) {
4307 key = strtol(tokens[j+1], &sp, 10);
4308 if ( key > 0 && key <= 16 ) {
4309 aliasp[aliasindex].kaku_keymap[nident] = 1 << (key - 1);
4310 }
4311 else {
4312 store_error_message("Invalid KAKU key parameter");
4313 return 1;
4314 }
4315
4316 if ( strchr(" \t\r\n", *sp) ) {
4317 nident++;
4318 continue;
4319 }
4320
4321 strupper(sp);
4322 if ( strlen(sp) == 1 && *sp >= 'A' && *sp <= 'P' ) {
4323 aliasp[aliasindex].kaku_grpmap[nident] = 1 << (*sp - 'A');
4324 }
4325 else {
4326 store_error_message("Invalid KAKU group parameter");
4327 return 1;
4328 }
4329 }
4330 else {
4331 strupper(tokens[j+1]);
4332 grp = *tokens[j+1];
4333 if ( strlen(tokens[j+1]) == 1 && grp >= 'A' && grp <= 'P' ) {
4334 aliasp[aliasindex].kaku_grpmap[nident] = 1 << (grp - 'A');
4335 }
4336 else {
4337 store_error_message("Invalid KAKU group parameter");
4338 return 1;
4339 }
4340 }
4341
4342 nident++;
4343 }
4344
4345 aliasp[aliasindex].nident = nident;
4346
4347
4348 aliasp[aliasindex].vtype = RF_KAKU;
4349
4350 aliasp[aliasindex].optflags = MOPT_KAKU;
4351
4352 return 0;
4353 }
4354