1 /*
2 * Hamlib Netrotctl backend - main file
3 * Copyright (c) 2001-2009 by Stephane Fillod
4 *
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <stdlib.h>
27 #include <string.h> /* String function definitions */
28 #include <unistd.h> /* UNIX standard function definitions */
29 #include <math.h>
30 #include <errno.h>
31
32 #include "hamlib/rotator.h"
33 #include "iofunc.h"
34 #include "misc.h"
35 #include "network.h"
36 #include "serial.h"
37
38 #include "rot_dummy.h"
39
40 #define CMD_MAX 32
41 #define BUF_MAX 64
42
43 /*
44 * Helper function with protocol return code parsing
45 */
netrotctl_transaction(ROT * rot,char * cmd,int len,char * buf)46 static int netrotctl_transaction(ROT *rot, char *cmd, int len, char *buf)
47 {
48 int ret;
49
50 /* flush anything in the read buffer before command is sent */
51 rig_flush(&rot->state.rotport);
52
53 ret = write_block(&rot->state.rotport, cmd, len);
54
55 if (ret != RIG_OK)
56 {
57 return ret;
58 }
59
60 ret = read_string(&rot->state.rotport, buf, BUF_MAX, "\n", sizeof("\n"));
61
62 if (ret < 0)
63 {
64 return ret;
65 }
66
67 if (!memcmp(buf, NETROTCTL_RET, strlen(NETROTCTL_RET)))
68 {
69 return atoi(buf + strlen(NETROTCTL_RET));
70 }
71
72 return ret;
73 }
74
netrotctl_open(ROT * rot)75 static int netrotctl_open(ROT *rot)
76 {
77 int ret, len;
78 struct rot_state *rs = &rot->state;
79 int prot_ver;
80 char cmd[CMD_MAX];
81 char buf[BUF_MAX];
82
83 rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
84
85
86 len = sprintf(cmd, "\\dump_state\n");
87
88 ret = netrotctl_transaction(rot, cmd, len, buf);
89
90 if (ret <= 0)
91 {
92 return (ret < 0) ? ret : -RIG_EPROTO;
93 }
94
95 prot_ver = atoi(buf);
96 #define ROTCTLD_PROT_VER 0
97
98 if (prot_ver < ROTCTLD_PROT_VER)
99 {
100 return -RIG_EPROTO;
101 }
102
103 ret = read_string(&rot->state.rotport, buf, BUF_MAX, "\n", sizeof("\n"));
104
105 if (ret <= 0)
106 {
107 return (ret < 0) ? ret : -RIG_EPROTO;
108 }
109
110 ret = read_string(&rot->state.rotport, buf, BUF_MAX, "\n", sizeof("\n"));
111
112 if (ret <= 0)
113 {
114 return (ret < 0) ? ret : -RIG_EPROTO;
115 }
116
117 rs->min_az = atof(buf);
118
119 ret = read_string(&rot->state.rotport, buf, BUF_MAX, "\n", sizeof("\n"));
120
121 if (ret <= 0)
122 {
123 return (ret < 0) ? ret : -RIG_EPROTO;
124 }
125
126 rs->max_az = atof(buf);
127
128 ret = read_string(&rot->state.rotport, buf, BUF_MAX, "\n", sizeof("\n"));
129
130 if (ret <= 0)
131 {
132 return (ret < 0) ? ret : -RIG_EPROTO;
133 }
134
135 rs->min_el = atof(buf);
136
137 ret = read_string(&rot->state.rotport, buf, BUF_MAX, "\n", sizeof("\n"));
138
139 if (ret <= 0)
140 {
141 return (ret < 0) ? ret : -RIG_EPROTO;
142 }
143
144 rs->max_el = atof(buf);
145
146 return RIG_OK;
147 }
148
netrotctl_close(ROT * rot)149 static int netrotctl_close(ROT *rot)
150 {
151 rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
152
153 /* clean signoff, no read back */
154 write_block(&rot->state.rotport, "q\n", 2);
155
156 return RIG_OK;
157 }
158
netrotctl_set_position(ROT * rot,azimuth_t az,elevation_t el)159 static int netrotctl_set_position(ROT *rot, azimuth_t az, elevation_t el)
160 {
161 int ret, len;
162 char cmd[CMD_MAX];
163 char buf[BUF_MAX];
164
165 rig_debug(RIG_DEBUG_VERBOSE, "%s called: %f %f\n", __func__,
166 az, el);
167
168 len = sprintf(cmd, "P %f %f\n", az, el);
169
170 ret = netrotctl_transaction(rot, cmd, len, buf);
171
172 if (ret > 0)
173 {
174 return -RIG_EPROTO;
175 }
176 else
177 {
178 return ret;
179 }
180 }
181
netrotctl_get_position(ROT * rot,azimuth_t * az,elevation_t * el)182 static int netrotctl_get_position(ROT *rot, azimuth_t *az, elevation_t *el)
183 {
184 int ret, len;
185 char cmd[CMD_MAX];
186 char buf[BUF_MAX];
187
188 rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
189
190 len = sprintf(cmd, "p\n");
191
192 ret = netrotctl_transaction(rot, cmd, len, buf);
193
194 if (ret <= 0)
195 {
196 return (ret < 0) ? ret : -RIG_EPROTO;
197 }
198
199 *az = atof(buf);
200
201 ret = read_string(&rot->state.rotport, buf, BUF_MAX, "\n", sizeof("\n"));
202
203 if (ret <= 0)
204 {
205 return (ret < 0) ? ret : -RIG_EPROTO;
206 }
207
208 *el = atof(buf);
209
210 return RIG_OK;
211 }
212
213
netrotctl_stop(ROT * rot)214 static int netrotctl_stop(ROT *rot)
215 {
216 int ret, len;
217 char cmd[CMD_MAX];
218 char buf[BUF_MAX];
219
220 rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
221
222 len = sprintf(cmd, "S\n");
223
224 ret = netrotctl_transaction(rot, cmd, len, buf);
225
226 if (ret > 0)
227 {
228 return -RIG_EPROTO;
229 }
230 else
231 {
232 return ret;
233 }
234 }
235
236
netrotctl_park(ROT * rot)237 static int netrotctl_park(ROT *rot)
238 {
239 int ret, len;
240 char cmd[CMD_MAX];
241 char buf[BUF_MAX];
242
243 rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
244
245 len = sprintf(cmd, "K\n");
246
247 ret = netrotctl_transaction(rot, cmd, len, buf);
248
249 if (ret > 0)
250 {
251 return -RIG_EPROTO;
252 }
253 else
254 {
255 return ret;
256 }
257 }
258
netrotctl_reset(ROT * rot,rot_reset_t reset)259 static int netrotctl_reset(ROT *rot, rot_reset_t reset)
260 {
261 int ret, len;
262 char cmd[CMD_MAX];
263 char buf[BUF_MAX];
264
265 rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
266
267 len = sprintf(cmd, "R %d\n", reset);
268
269 ret = netrotctl_transaction(rot, cmd, len, buf);
270
271 if (ret > 0)
272 {
273 return -RIG_EPROTO;
274 }
275 else
276 {
277 return ret;
278 }
279 }
280
netrotctl_move(ROT * rot,int direction,int speed)281 static int netrotctl_move(ROT *rot, int direction, int speed)
282 {
283 int ret, len;
284 char cmd[CMD_MAX];
285 char buf[BUF_MAX];
286
287 rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
288
289 len = sprintf(cmd, "M %d %d\n", direction, speed);
290
291 ret = netrotctl_transaction(rot, cmd, len, buf);
292
293 if (ret > 0)
294 {
295 return -RIG_EPROTO;
296 }
297 else
298 {
299 return ret;
300 }
301 }
302
netrotctl_get_info(ROT * rot)303 static const char *netrotctl_get_info(ROT *rot)
304 {
305 int ret, len;
306 char cmd[CMD_MAX];
307 static char buf[BUF_MAX];
308
309 rig_debug(RIG_DEBUG_VERBOSE, "%s called\n", __func__);
310
311 len = sprintf(cmd, "_\n");
312
313 ret = netrotctl_transaction(rot, cmd, len, buf);
314
315 if (ret < 0)
316 {
317 return NULL;
318 }
319
320 buf [ret] = '\0';
321
322 return buf;
323 }
324
325
326
327 /*
328 * NET rotctl capabilities.
329 */
330
331 const struct rot_caps netrotctl_caps =
332 {
333 ROT_MODEL(ROT_MODEL_NETROTCTL),
334 .model_name = "NET rotctl",
335 .mfg_name = "Hamlib",
336 .version = "20200528.0",
337 .copyright = "LGPL",
338 .status = RIG_STATUS_STABLE,
339 .rot_type = ROT_TYPE_OTHER,
340 .port_type = RIG_PORT_NETWORK,
341 .timeout = 2000,
342 .retry = 3,
343
344 .min_az = -180.,
345 .max_az = 180.,
346 .min_el = 0.,
347 .max_el = 90.,
348
349 .priv = NULL, /* priv */
350
351 /* .rot_init = netrotctl_init, */
352 /* .rot_cleanup = netrotctl_cleanup, */
353 .rot_open = netrotctl_open,
354 .rot_close = netrotctl_close,
355
356 .set_position = netrotctl_set_position,
357 .get_position = netrotctl_get_position,
358 .park = netrotctl_park,
359 .stop = netrotctl_stop,
360 .reset = netrotctl_reset,
361 .move = netrotctl_move,
362
363 .get_info = netrotctl_get_info,
364 };
365
366