1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
/*
* SerialCommand.hpp
*
* Copyright 2020 Kevin Krüger <kkevin@gmx.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*
*/
#ifndef _SERIALCOMMAND_H_INCLUDED_
#define _SERIALCOMMAND_H_INCLUDED_
#include <cstdint>
#include <vector>
#include <chrono>
#include <cmath>
#include <ctime>
#include <libnova/julian_day.h>
#include "config.h"
#define MESSAGE_FRAME_SIZE (13)
namespace SerialDeviceControl
{
//After determining the message frame size and structure,
//these commands where found to affect the telescope controller (Handbox + Motors).
//If an invalid command is issued the telescope controller stops reporting its status,
//until another valid command is issued.
//Command IDs which did not stop the report messages are considered effective and are listed below:
enum SerialCommandID
{
//a null command message.
NULL_COMMAND_ID = (uint8_t) 0x00,
//these command IDs move the telescope in certain direction while tracking:
//move the telescope "east".
MOVE_EAST_COMMAND_ID = (uint8_t)0x01,
//move the telescope "west".
MOVE_WEST_COMMAND_ID = (uint8_t)0x02,
//move the telescope "north".
MOVE_NORTH_COMMAND_ID = (uint8_t)0x04,
//move the telescope "south".
MOVE_SOUTH_COMMAND_ID = (uint8_t)0x08,
//immediatly stops slewing the telescope.
STOP_MOTION_COMMAND_ID = (uint8_t)0x1D,
//slews the telescope back into the park/initial position.
PARK_COMMAND_ID = (uint8_t)0x1E,
//Requests the site location geodesic coordinates from the controller.
GET_SITE_LOCATION_COMMAND_ID = (uint8_t)0x1f,
//Tell the mount to gracefully disconnect the driver from the serial protocol. Stops the mount from sending status reports.
DISCONNET_COMMAND_ID = (uint8_t) 0x22,
//Slews the telescope to the equatorial coordinates provided.
GOTO_COMMAND_ID = (uint8_t)0x23,
//Tell the controller to match/align to the delivered coordinates. This updates the scope alignment.
SYNC_COMMAND_ID = (uint8_t)0x24,
//sets the site location on the telescope controller.
SET_SITE_LOCATION_COMMAND_ID = (uint8_t)0x25,
//sets time and date on the telescope controller.
SET_DATE_TIME_COMMAND_ID = (uint8_t)0x26,
//If the GET_SITE_LOCATION message was sent, the controller responds with this message, along side the Geo-Coordinates.
TELESCOPE_SITE_LOCATION_REPORT_COMMAND_ID = (uint8_t)0xfe,
//This id is used when the telescope is in an untracked state. Found in the C# implementation but apparently not used.
TELESCOPE_POSITION_REPORT_UNTRACKED_COMMAND_ID = (uint8_t)0xf0,
//This id is used by the telescope controller to announce its pointing coordinates.
TELESCOPE_POSITION_REPORT_COMMAND_ID = (uint8_t)0xff
};
//Simple data structure for a coordinate pair.
struct EquatorialCoordinates
{
//The time stamp when this coordinates where received.
std::chrono::time_point<std::chrono::system_clock> TimeStamp;
//decimal value of the right ascension.
float RightAscension;
//decimal value of the declination.
float Declination;
static EquatorialCoordinates Delta(EquatorialCoordinates &first, EquatorialCoordinates &second)
{
EquatorialCoordinates result;
result.RightAscension = first.RightAscension - second.RightAscension;
result.Declination = first.RightAscension - second.RightAscension;
return result;
}
static float Absolute(EquatorialCoordinates &deltaCoordinates)
{
float a = deltaCoordinates.RightAscension;
float b = deltaCoordinates.Declination;
float abs = std::fabs(a * a + b * b);
return abs;
}
};
//Enum with month names for easy legibility.
enum DateMonths
{
January = 1,
February = 2,
March = 3,
April = 4,
May = 5,
June = 6,
July = 7,
August = 8,
September = 9,
October = 10,
November = 11,
December = 12,
};
//helper union to read out float bytes without the hazzle with pointers
union FloatByteConverter
{
uint8_t bytes[4];
float decimal_number;
};
//Simple static class providing the message generation mechanisms.
//The message frame size is 13 bytes, a 4 byte header/preamble,
//a one byte command followed by 2 to 6 arguments,
//distributed over the 8 remaining bytes.
//see the Get...Message() implementations for details.
//Since the serial protocol is faily simple, a lot of the error handling is on the client side to avoid the controller to go haywire.
class SerialCommand
{
private:
//helper function pushing a number of bytes into the buffer, for padding.
static void push_bytes(std::vector<uint8_t> &buffer, uint8_t byte, size_t count);
//simple constant containing the message header as of firmware V2.3.
static uint8_t MessageHeader[4];
//helper function to push the float values into the buffer
static void push_float_bytes(std::vector<uint8_t> &buffer, FloatByteConverter &values);
public:
//Gracefully disconnect from the GoTo Controller.
//returns false if an error occurs.
static bool GetDisconnectCommandMessage(std::vector<uint8_t> &buffer);
//put the stop message into the buffer provided.
//returns false if an error occurs.
static bool GetStopMotionCommandMessage(std::vector<uint8_t> &buffer);
//put the park message into the buffer provided.
//returns false if an error occurs.
static bool GetParkCommandMessage(std::vector<uint8_t> &buffer);
//put the get site location message into the buffer provided.
//returns false if an error occurs.
static bool GetGetSiteLocationCommandMessage(std::vector<uint8_t> &buffer);
//put the goto message corresponding to the coordinates provided into the buffer provided.
//returns false if an error occurs.
static bool GetGotoCommandMessage(std::vector<uint8_t> &buffer, float decimal_right_ascension, float decimal_declination);
//put the sync message corresponding to the coordinates provided into the buffer provided.
//This function is used when plate solving.
//returns false if an error occurs.
static bool GetSyncCommandMessage(std::vector<uint8_t> &buffer, float decimal_right_ascension, float decimal_declination);
//put the set site location message corresponding the coordinates provided into the buffer provided
//returns false if an error occurs.
static bool GetSetSiteLocationCommandMessage(std::vector<uint8_t> &buffer, float decimal_latitude, float decimal_longitude);
//put the date time message corresponding to the time/date provided into the buffer provided.
//returns false if an error occurs.
static bool GetSetDateTimeCommandMessage(std::vector<uint8_t> &buffer, uint16_t year, uint8_t month, uint8_t day,
uint8_t hour, uint8_t minute, uint8_t second, int8_t utc_offset);
//move the telescope in a certain direction. Use the first 4 command IDs for a particular direction.
static bool GetMoveWhileTrackingCommandMessage(std::vector<uint8_t> &buffer, SerialCommandID direction);
//helper function pushing the header into the buffer.
static void PushHeader(std::vector<uint8_t> &buffer);
};
}
#endif
|