2020-10-27 12:22:10 -04:00
///////////////////////////////////////////////////////////////////////////////////
2023-11-18 07:12:18 -05:00
// Copyright (C) 2020-2023 Jon Beniston, M7RCE <jon@beniston.com> //
// Copyright (C) 2021 Christoph Berg <myon@debian.org> //
// Copyright (C) 2022 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// Copyright (C) 2022 Jiří Pinkava <jiri.pinkava@rossum.ai> //
2020-10-27 12:22:10 -04:00
// //
// 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 as version 3 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 V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
2021-02-26 15:27:35 -05:00
# include <algorithm>
2021-05-30 07:52:01 -04:00
# include <cmath>
2021-02-26 15:27:35 -05:00
2020-10-27 12:22:10 -04:00
# include <QDebug>
# include <QSerialPort>
# include <QRegularExpression>
2024-02-14 08:21:26 -05:00
# include "maincore.h"
# include "util/astronomy.h"
# include "SWGTargetAzimuthElevation.h"
2021-01-13 14:44:53 -05:00
# include "gs232controller.h"
2020-10-27 12:22:10 -04:00
# include "gs232controllerworker.h"
# include "gs232controllerreport.h"
MESSAGE_CLASS_DEFINITION ( GS232ControllerWorker : : MsgConfigureGS232ControllerWorker , Message )
MESSAGE_CLASS_DEFINITION ( GS232ControllerReport : : MsgReportAzAl , Message )
2024-02-14 08:21:26 -05:00
GS232ControllerWorker : : GS232ControllerWorker ( GS232Controller * controller ) :
m_controller ( controller ) ,
2020-10-27 12:22:10 -04:00
m_msgQueueToFeature ( nullptr ) ,
2021-11-23 07:13:24 -05:00
m_device ( nullptr ) ,
2021-11-25 04:28:59 -05:00
m_serialPort ( this ) ,
m_socket ( this ) ,
m_pollTimer ( this ) ,
2021-05-30 07:38:07 -04:00
m_lastAzimuth ( - 1.0f ) ,
m_lastElevation ( - 1.0f ) ,
2023-04-03 11:47:13 -04:00
m_controllerProtocol ( nullptr )
// m_spidSetOutstanding(false),
// m_spidSetSent(false),
// m_spidStatusSent(false),
// m_rotCtlDReadAz(false)
2020-10-27 12:22:10 -04:00
{
}
GS232ControllerWorker : : ~ GS232ControllerWorker ( )
{
2022-09-18 11:47:06 -04:00
qDebug ( ) < < " GS232ControllerWorker::~GS232ControllerWorker " ;
2022-09-20 16:13:12 -04:00
stopWork ( ) ;
2020-10-27 12:22:10 -04:00
m_inputMessageQueue . clear ( ) ;
2023-04-03 11:47:13 -04:00
delete m_controllerProtocol ;
2020-10-27 12:22:10 -04:00
}
2022-09-18 11:47:06 -04:00
void GS232ControllerWorker : : startWork ( )
2020-10-27 12:22:10 -04:00
{
2022-09-18 11:47:06 -04:00
qDebug ( ) < < " GS232ControllerWorker::startWork " ;
2020-10-27 12:22:10 -04:00
connect ( & m_inputMessageQueue , SIGNAL ( messageEnqueued ( ) ) , this , SLOT ( handleInputMessages ( ) ) ) ;
2021-11-23 07:13:24 -05:00
connect ( & m_serialPort , & QSerialPort : : readyRead , this , & GS232ControllerWorker : : readData ) ;
connect ( & m_socket , & QTcpSocket : : readyRead , this , & GS232ControllerWorker : : readData ) ;
if ( m_settings . m_connection = = GS232ControllerSettings : : TCP ) {
m_device = openSocket ( m_settings ) ;
} else {
m_device = openSerialPort ( m_settings ) ;
2021-05-30 07:38:07 -04:00
}
2022-03-03 06:06:18 -05:00
connect ( & m_pollTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( update ( ) ) ) ;
m_pollTimer . start ( 1000 ) ;
2022-09-18 11:47:06 -04:00
// Handle any messages already on the queue
handleInputMessages ( ) ;
2020-10-27 12:22:10 -04:00
}
void GS232ControllerWorker : : stopWork ( )
{
2022-09-18 11:47:06 -04:00
qDebug ( ) < < " GS232ControllerWorker::stopWork " ;
2022-03-03 06:06:18 -05:00
disconnect ( & m_inputMessageQueue , SIGNAL ( messageEnqueued ( ) ) , this , SLOT ( handleInputMessages ( ) ) ) ;
2022-11-18 05:55:15 -05:00
if ( m_device & & m_device - > isOpen ( ) )
{
2021-11-23 07:13:24 -05:00
m_device - > close ( ) ;
2022-11-18 05:55:15 -05:00
m_device = nullptr ;
2021-11-23 07:13:24 -05:00
}
disconnect ( & m_serialPort , & QSerialPort : : readyRead , this , & GS232ControllerWorker : : readData ) ;
disconnect ( & m_socket , & QTcpSocket : : readyRead , this , & GS232ControllerWorker : : readData ) ;
2022-03-03 06:06:18 -05:00
m_pollTimer . stop ( ) ;
disconnect ( & m_pollTimer , SIGNAL ( timeout ( ) ) , this , SLOT ( update ( ) ) ) ;
2020-10-27 12:22:10 -04:00
}
void GS232ControllerWorker : : handleInputMessages ( )
{
Message * message ;
while ( ( message = m_inputMessageQueue . pop ( ) ) ! = nullptr )
{
if ( handleMessage ( * message ) ) {
delete message ;
}
}
}
bool GS232ControllerWorker : : handleMessage ( const Message & cmd )
{
if ( MsgConfigureGS232ControllerWorker : : match ( cmd ) )
{
MsgConfigureGS232ControllerWorker & cfg = ( MsgConfigureGS232ControllerWorker & ) cmd ;
2022-11-24 10:40:36 -05:00
applySettings ( cfg . getSettings ( ) , cfg . getSettingsKeys ( ) , cfg . getForce ( ) ) ;
2020-10-27 12:22:10 -04:00
return true ;
}
else
{
return false ;
}
}
2022-11-24 10:40:36 -05:00
void GS232ControllerWorker : : applySettings ( const GS232ControllerSettings & settings , const QList < QString > & settingsKeys , bool force )
2020-10-27 12:22:10 -04:00
{
2022-11-24 10:40:36 -05:00
qDebug ( ) < < " GS232ControllerWorker::applySettings: " < < settings . getDebugString ( settingsKeys , force ) < < " force: " < < force ;
2023-04-03 11:47:13 -04:00
if ( ( settingsKeys . contains ( " protocol " ) & & ( settings . m_protocol ! = m_settings . m_protocol ) ) | | force )
{
delete m_controllerProtocol ;
m_controllerProtocol = ControllerProtocol : : create ( settings . m_protocol ) ;
if ( m_controllerProtocol )
{
m_controllerProtocol - > setMessageQueue ( m_msgQueueToFeature ) ;
m_controllerProtocol - > setDevice ( m_device ) ;
}
}
2022-11-24 10:40:36 -05:00
if ( settingsKeys . contains ( " connection " ) )
2020-10-27 12:22:10 -04:00
{
2022-11-18 05:55:15 -05:00
if ( m_device & & m_device - > isOpen ( ) )
{
2021-11-23 07:13:24 -05:00
m_device - > close ( ) ;
2022-11-18 05:55:15 -05:00
m_device = nullptr ;
2021-11-23 07:13:24 -05:00
}
2020-10-27 12:22:10 -04:00
}
2021-11-23 07:13:24 -05:00
if ( settings . m_connection = = GS232ControllerSettings : : TCP )
2020-10-27 12:22:10 -04:00
{
2023-04-03 11:47:13 -04:00
if ( settingsKeys . contains ( " host " ) | | settingsKeys . contains ( " port " ) | | force )
{
2021-11-23 07:13:24 -05:00
m_device = openSocket ( settings ) ;
2023-04-03 11:47:13 -04:00
if ( m_controllerProtocol ) {
m_controllerProtocol - > setDevice ( m_device ) ;
}
2021-11-23 07:13:24 -05:00
}
}
else
{
2023-04-03 11:47:13 -04:00
if ( settingsKeys . contains ( " serialPort " ) | | force )
{
2021-11-23 07:13:24 -05:00
m_device = openSerialPort ( settings ) ;
2023-04-03 11:47:13 -04:00
if ( m_controllerProtocol ) {
m_controllerProtocol - > setDevice ( m_device ) ;
}
}
else if ( settingsKeys . contains ( " baudRate " ) | | force )
{
2021-11-23 07:13:24 -05:00
m_serialPort . setBaudRate ( settings . m_baudRate ) ;
}
2020-10-27 12:22:10 -04:00
}
2023-01-06 04:18:02 -05:00
if ( force ) {
m_settings = settings ;
} else {
m_settings . applySettings ( settingsKeys , settings ) ;
}
2023-04-03 11:47:13 -04:00
if ( m_controllerProtocol ) {
m_controllerProtocol - > applySettings ( settings , settingsKeys , force ) ;
}
2022-11-18 05:55:15 -05:00
if ( m_device ! = nullptr )
{
// Apply offset then clamp
2021-02-26 15:27:35 -05:00
2022-11-18 05:55:15 -05:00
float azimuth , elevation ;
settings . calcTargetAzEl ( azimuth , elevation ) ;
2021-05-30 07:38:07 -04:00
2022-11-18 05:55:15 -05:00
// Don't set if within tolerance of last setting
float azDiff = std : : abs ( azimuth - m_lastAzimuth ) ;
float elDiff = std : : abs ( elevation - m_lastElevation ) ;
2021-02-26 15:27:35 -05:00
2022-11-18 05:55:15 -05:00
if ( ( ( elDiff > settings . m_tolerance ) | | ( m_lastElevation = = - 1 ) | | force ) & & ( settings . m_elevationMax ! = 0 ) )
{
setAzimuthElevation ( azimuth , elevation ) ;
}
else if ( ( azDiff > settings . m_tolerance ) | | ( m_lastAzimuth = = - 1 ) | | force )
{
setAzimuth ( azimuth ) ;
}
2024-02-14 08:21:26 -05:00
sendToSkyMap ( azimuth , elevation ) ;
2020-10-27 12:22:10 -04:00
}
}
2021-11-23 07:13:24 -05:00
QIODevice * GS232ControllerWorker : : openSerialPort ( const GS232ControllerSettings & settings )
2021-02-26 15:27:35 -05:00
{
2021-11-23 07:13:24 -05:00
qDebug ( ) < < " GS232ControllerWorker::openSerialPort: " < < settings . m_serialPort ;
2021-05-30 07:38:07 -04:00
if ( m_serialPort . isOpen ( ) ) {
2021-02-26 15:27:35 -05:00
m_serialPort . close ( ) ;
2021-05-30 07:38:07 -04:00
}
2021-11-23 07:13:24 -05:00
m_lastAzimuth = - 1 ;
m_lastElevation = - 1 ;
if ( ! settings . m_serialPort . isEmpty ( ) )
2021-02-26 15:27:35 -05:00
{
2021-11-23 07:13:24 -05:00
m_serialPort . setPortName ( settings . m_serialPort ) ;
m_serialPort . setBaudRate ( settings . m_baudRate ) ;
if ( ! m_serialPort . open ( QIODevice : : ReadWrite ) )
{
qCritical ( ) < < " GS232ControllerWorker::openSerialPort: Failed to open serial port " < < settings . m_serialPort < < " . Error: " < < m_serialPort . error ( ) ;
2021-02-26 15:27:35 -05:00
m_msgQueueToFeature - > push ( GS232Controller : : MsgReportWorker : : create ( QString ( " Failed to open serial port %1: %2 " ) . arg ( settings . m_serialPort ) . arg ( m_serialPort . error ( ) ) ) ) ;
2021-11-23 07:13:24 -05:00
return nullptr ;
2021-05-30 07:38:07 -04:00
}
2021-11-23 07:13:24 -05:00
else
{
return & m_serialPort ;
}
}
else
{
return nullptr ;
}
}
QIODevice * GS232ControllerWorker : : openSocket ( const GS232ControllerSettings & settings )
{
qDebug ( ) < < " GS232ControllerWorker::openSocket: " < < settings . m_host < < settings . m_port ;
if ( m_socket . isOpen ( ) ) {
m_socket . close ( ) ;
2021-02-26 15:27:35 -05:00
}
m_lastAzimuth = - 1 ;
m_lastElevation = - 1 ;
2021-11-23 07:13:24 -05:00
m_socket . connectToHost ( settings . m_host , settings . m_port ) ;
if ( m_socket . waitForConnected ( 3000 ) )
{
return & m_socket ;
}
else
{
qCritical ( ) < < " GS232ControllerWorker::openSocket: Failed to connect to " < < settings . m_host < < settings . m_port ;
m_msgQueueToFeature - > push ( GS232Controller : : MsgReportWorker : : create ( QString ( " Failed to connect to %1:%2 " ) . arg ( settings . m_host ) . arg ( settings . m_port ) ) ) ;
return nullptr ;
}
2021-02-26 15:27:35 -05:00
}
2021-05-30 07:38:07 -04:00
void GS232ControllerWorker : : setAzimuth ( float azimuth )
2020-10-27 12:22:10 -04:00
{
2023-04-03 11:47:13 -04:00
if ( m_device & & m_device - > isOpen ( ) & & m_controllerProtocol ) {
m_controllerProtocol - > setAzimuth ( azimuth ) ;
2021-05-30 07:38:07 -04:00
}
2023-04-03 11:47:13 -04:00
2021-05-30 07:38:07 -04:00
m_lastAzimuth = azimuth ;
2020-10-27 12:22:10 -04:00
}
2021-05-30 07:38:07 -04:00
void GS232ControllerWorker : : setAzimuthElevation ( float azimuth , float elevation )
2020-10-27 12:22:10 -04:00
{
2023-04-03 11:47:13 -04:00
if ( m_device & & m_device - > isOpen ( ) & & m_controllerProtocol ) {
m_controllerProtocol - > setAzimuthElevation ( azimuth , elevation ) ;
2021-05-30 07:38:07 -04:00
}
m_lastAzimuth = azimuth ;
m_lastElevation = elevation ;
2020-10-27 12:22:10 -04:00
}
2021-11-23 07:13:24 -05:00
void GS232ControllerWorker : : readData ( )
2020-10-27 12:22:10 -04:00
{
2023-04-03 11:47:13 -04:00
if ( m_controllerProtocol ) {
m_controllerProtocol - > readData ( ) ;
2020-10-27 12:22:10 -04:00
}
}
void GS232ControllerWorker : : update ( )
{
2021-11-23 07:13:24 -05:00
// Request current Az/El from controller
2023-04-03 11:47:13 -04:00
if ( m_device & & m_device - > isOpen ( ) & & m_controllerProtocol ) {
m_controllerProtocol - > update ( ) ;
2020-10-27 12:22:10 -04:00
}
}
2023-04-03 11:47:13 -04:00
2024-02-14 08:21:26 -05:00
void GS232ControllerWorker : : sendToSkyMap ( float azimuth , float elevation )
{
QList < ObjectPipe * > targetPipes ;
MainCore : : instance ( ) - > getMessagePipes ( ) . getMessagePipes ( m_controller , " target " , targetPipes ) ;
for ( const auto & pipe : targetPipes )
{
MessageQueue * messageQueue = qobject_cast < MessageQueue * > ( pipe - > m_element ) ;
SWGSDRangel : : SWGTargetAzimuthElevation * swgTarget = new SWGSDRangel : : SWGTargetAzimuthElevation ( ) ;
swgTarget - > setName ( new QString ( " Rotator " ) ) ;
swgTarget - > setAzimuth ( azimuth ) ;
swgTarget - > setElevation ( elevation ) ;
messageQueue - > push ( MainCore : : MsgTargetAzimuthElevation : : create ( m_controller , swgTarget ) ) ;
}
}