Instrument Neutral Distributed Interface INDI 2.2.5
ikunfocuser_protocol.cpp
Go to the documentation of this file.
1/*
2 IKunFocuser protocol helpers
3 Copyright (C) 2026 IKunFocuser contributors
4 SPDX-License-Identifier: LGPL-2.1-or-later
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
13
14#include <cerrno>
15#include <cstdlib>
16
17namespace
18{
19
20bool findJsonValue(const std::string &json, const std::string &key, std::size_t &valueStart)
21{
22 const std::string token = "\"" + key + "\"";
23 const auto keyStart = json.find(token);
24 if (keyStart == std::string::npos)
25 return false;
26
27 const auto colon = json.find(':', keyStart + token.size());
28 if (colon == std::string::npos)
29 return false;
30
31 valueStart = json.find_first_not_of(" \t\r\n", colon + 1);
32 return valueStart != std::string::npos;
33}
34
35} // namespace
36
38{
39
40bool parseMotionStatus(const std::string &response, MotionStatus &status)
41{
42 const auto positionMarker = response.find("P ");
43 const auto movingMarker = response.find(";M ");
44 if (positionMarker == std::string::npos || movingMarker == std::string::npos || movingMarker <= positionMarker + 2)
45 return false;
46
47 const std::string positionText = response.substr(positionMarker + 2, movingMarker - (positionMarker + 2));
48 char *end = nullptr;
49 errno = 0;
50 const long long parsedPosition = std::strtoll(positionText.c_str(), &end, 10);
51 if (errno != 0 || end == positionText.c_str() || *end != '\0' || parsedPosition < 0)
52 return false;
53
54 const auto movingStart = movingMarker + 3;
55 bool parsedMoving = false;
56 if (response.compare(movingStart, 4, "true") == 0)
57 parsedMoving = true;
58 else if (response.compare(movingStart, 5, "false") != 0)
59 return false;
60
61 status.position = parsedPosition;
62 status.moving = parsedMoving;
63 return true;
64}
65
66bool parseVersion(const std::string &response, int &version)
67{
68 const auto marker = response.find("V ");
69 if (marker == std::string::npos)
70 return false;
71
72 const char *start = response.c_str() + marker + 2;
73 char *end = nullptr;
74 errno = 0;
75 const long parsed = std::strtol(start, &end, 10);
76 if (errno != 0 || end == start || parsed <= 0)
77 return false;
78
79 version = static_cast<int>(parsed);
80 return true;
81}
82
83bool parseJsonInteger(const std::string &json, const std::string &key, int64_t &value)
84{
85 std::size_t start = 0;
86 if (!findJsonValue(json, key, start))
87 return false;
88
89 char *end = nullptr;
90 errno = 0;
91 const long long parsed = std::strtoll(json.c_str() + start, &end, 10);
92 if (errno != 0 || end == json.c_str() + start)
93 return false;
94
95 value = parsed;
96 return true;
97}
98
99bool parseJsonNumber(const std::string &json, const std::string &key, double &value)
100{
101 std::size_t start = 0;
102 if (!findJsonValue(json, key, start))
103 return false;
104
105 char *end = nullptr;
106 errno = 0;
107 const double parsed = std::strtod(json.c_str() + start, &end);
108 if (errno != 0 || end == json.c_str() + start)
109 return false;
110
111 value = parsed;
112 return true;
113}
114
115bool parseJsonBoolean(const std::string &json, const std::string &key, bool &value)
116{
117 std::size_t start = 0;
118 if (!findJsonValue(json, key, start))
119 return false;
120
121 if (json.compare(start, 4, "true") == 0)
122 {
123 value = true;
124 return true;
125 }
126
127 if (json.compare(start, 5, "false") == 0)
128 {
129 value = false;
130 return true;
131 }
132
133 return false;
134}
135
136bool isErrorResponse(const std::string &response)
137{
138 return response.find("ERR:") != std::string::npos;
139}
140
141bool isSupportedIdentity(const std::string &response)
142{
143 return response.find("EFucoser") != std::string::npos;
144}
145
146const char *modelForVersion(int version)
147{
148 if (version >= 1200 && version < 1300)
149 return "Arduino Nano ULN2003";
150 if (version >= 1100 && version < 1200)
151 return "ESP8266 ULN2003";
152 if (version >= 1000 && version < 1100)
153 return "ESP8266 STEP/DIR";
154 return "EFucoser";
155}
156
157bool isSupportedVersion(int version)
158{
159 return (version >= 1201 && version < 1300) ||
160 (version >= 1103 && version < 1200) ||
161 (version >= 1005 && version < 1100);
162}
163
164} // namespace IKunFocuserProtocol
a class to store JSON values
iterator find(const typename object_t::key_type &key)
find an element in a JSON object
int errno
bool parseJsonBoolean(const std::string &json, const std::string &key, bool &value)
const char * modelForVersion(int version)
bool isSupportedIdentity(const std::string &response)
bool isErrorResponse(const std::string &response)
bool isSupportedVersion(int version)
bool parseJsonNumber(const std::string &json, const std::string &key, double &value)
bool parseMotionStatus(const std::string &response, MotionStatus &status)
bool parseVersion(const std::string &response, int &version)
bool parseJsonInteger(const std::string &json, const std::string &key, int64_t &value)