diff --git a/src/event_server.cpp b/src/event_server.cpp index 6265c0644..077ffc0a7 100644 --- a/src/event_server.cpp +++ b/src/event_server.cpp @@ -33,6 +33,7 @@ */ #include "phd.h" +#include "event_server.h" #include #include @@ -116,10 +117,16 @@ struct JSeq close(); return m_s; } + + JSeq& operator<<(JSeq& other) { return *this << other.str(); } }; -typedef JSeq<'[', ']'> JAry; -typedef JSeq<'{', '}'> JObj; +struct JAry : public JSeq<'[', ']'> +{ +}; +struct JObj : public JSeq<'{', '}'> +{ +}; static JAry& operator<<(JAry& a, const wxString& str) { @@ -3055,3 +3062,136 @@ void EventServer::NotifyConfigurationChange() do_notify(m_eventServerClients, ev); m_configEventDebouncer->StartOnce(0); } + +MultiStarReport::Item::Item() : X(0), Y(0), ReferenceX(0), ReferenceY(0), Mass(0), SNR(0), HFD(0), status(0) { } + +MultiStarReport::Item MultiStarReport::Item::healthy(const GuideStar& star) +{ + return unhealthy(star, MultiStarReport::Item::Healthy); +} + +MultiStarReport::Item MultiStarReport::Item::unused(const GuideStar& star) +{ + return unhealthy(star, MultiStarReport::Item::Unused); +} + +MultiStarReport::Item MultiStarReport::Item::unhealthy(const GuideStar& star, uint8_t status) +{ + Item ret; + ret.X = star.X; + ret.Y = star.Y; + ret.ReferenceX = star.referencePoint.X; + ret.ReferenceY = star.referencePoint.Y; + ret.Mass = star.Mass; + ret.SNR = star.SNR; + ret.HFD = star.HFD; + ret.status = status; + return ret; +} + +MultiStarReport::MultiStarReport() : refined(false), stabilizing(false) { } + +void MultiStarReport::send() +{ + EvtServer.NotifyMultiStarStatus(*this); +} + +void MultiStarReport::addStar(MultiStarReport::Item star) +{ + stars.push_back(star); +} + +uint8_t MultiStarReport::Item::Missed(uint8_t count) +{ + return 40 + count; +} + +void MultiStarReport::setRefined(bool refined) +{ + this->refined = refined; +} + +void MultiStarReport::setStabilizing(bool stabilizing) +{ + this->stabilizing = stabilizing; +} + +static std::string statusStr(uint8_t status) +{ + switch (status) + { + case MultiStarReport::Item::Unused: + return "Unused"; + case MultiStarReport::Item::Healthy: + return "Healthy"; + case MultiStarReport::Item::ZeroDelta: + return "DZ"; + case MultiStarReport::Item::TooFar: + return "F"; + case MultiStarReport::Item::Reset: + return "R"; + case MultiStarReport::Item::Lost: + return "L"; + case MultiStarReport::Item::InvalidMass: + return "M"; + default: + if (status >= 40) + { + return "M" + std::to_string(status - 40); + } + return "Unknown(" + std::to_string(status) + ")"; + } +} + +void MultiStarReport::Item::toJObj(JObj& result) const +{ + result << NV("X", this->X); + result << NV("Y", this->Y); + result << NV("RefX", this->ReferenceX); + result << NV("RefY", this->ReferenceY); + result << NV("Mass", this->Mass); + result << NV("SNR", this->SNR); + result << NV("HFD", this->HFD); + if (this->status == MultiStarReport::Item::Unused) + { + result << NV("used", false); + } + else + { + result << NV("used", true); + if (this->status == MultiStarReport::Item::Healthy) + { + result << NV("err", NULL_VALUE); + } + else + { + result << NV("err", statusStr(this->status)); + } + } +} + +void MultiStarReport::toJObj(JObj& ev) const +{ + JAry stars; + for (size_t i = 0; i < this->stars.size(); i++) + { + JObj star; + this->stars[i].toJObj(star); + stars << star; + } + + ev << NV("Stars", stars); + ev << NV("Refined", this->refined); + ev << NV("Stabilizing", this->stabilizing); +} + +void EventServer::NotifyMultiStarStatus(const MultiStarReport& pos) +{ + if (m_eventServerClients.empty()) + return; + + Ev ev("MultiStarReport"); + pos.toJObj(ev); + + do_notify(m_eventServerClients, ev); +} \ No newline at end of file diff --git a/src/event_server.h b/src/event_server.h index 830755b03..9526aaaa6 100644 --- a/src/event_server.h +++ b/src/event_server.h @@ -36,8 +36,87 @@ #define EVENT_SERVER_INCLUDED #include +#include #include "json_parser.h" +struct JObj; +struct JAry; + +class MultiStarReport +{ +public: + class Item + { + friend class MultiStarReport; + + protected: + double Mass; + double SNR; + double HFD; + double ReferenceX, ReferenceY; + double X, Y; + uint8_t status; + Item(); + + void toJObj(JObj& obj) const; + + public: + static constexpr uint8_t Unused = 0; + static constexpr uint8_t Healthy = 1; + // Star ignore because one delta is exaclty zero + static constexpr uint8_t ZeroDelta = 2; + // Star is too far from reference + static constexpr uint8_t TooFar = 3; + // Star was reset due to beeing too far for too long + static constexpr uint8_t Reset = 4; + // Star lost + static constexpr uint8_t Lost = 5; + // Mass does not match + static constexpr uint8_t InvalidMass = 6; + static uint8_t Missed(uint8_t missCount); + + static Item healthy(const GuideStar& star); + static Item unhealthy(const GuideStar& star, uint8_t reason); + static Item unused(const GuideStar& star); + }; + + std::vector stars; + bool stabilizing = false; + bool refined = false; + +public: + MultiStarReport(); + + void addStar(Item star); + void send(); + void setRefined(bool refined); + void setStabilizing(bool stabilizing); + + void toJObj(JObj& obj) const; +}; + +template +class DeferedEvent +{ +private: + bool emitted; + +public: + M value; + void send() + { + if (!emitted) + { + emitted = true; + value.send(); + } + } + + DeferedEvent() : value(), emitted(false) { } + + ~DeferedEvent() { send(); } +}; + class EventServer : public wxEvtHandler { public: @@ -63,6 +142,7 @@ class EventServer : public wxEvtHandler void NotifyLooping(unsigned int exposure, const Star *star, const FrameDroppedInfo *info); void NotifyLoopingStopped(); void NotifySingleFrameComplete(bool succeeded, const wxString& errorMsg, const SingleExposure& info); + void NotifyMultiStarStatus(const MultiStarReport& p); void NotifyStarSelected(const PHD_Point& pos); void NotifyStarLost(const FrameDroppedInfo& info); void NotifyGuidingStarted(); diff --git a/src/guider.cpp b/src/guider.cpp index a8ec7ee5c..233e78f65 100644 --- a/src/guider.cpp +++ b/src/guider.cpp @@ -32,6 +32,7 @@ * */ #include "phd.h" +#include "event_server.h" #include "nudge_lock.h" #include "comet_tool.h" #include "polardrift_tool.h" @@ -1307,8 +1308,8 @@ void Guider::UpdateGuideState(usImage *pImage, bool bStopping) GuiderOffset ofs; FrameDroppedInfo info; - - if (UpdateCurrentPosition(pImage, &ofs, &info)) // true means error + DeferedEvent frameStarPositions; + if (UpdateCurrentPosition(pImage, &ofs, &info, &frameStarPositions.value)) // true means error { info.frameNumber = pImage->FrameNum; info.time = pFrame->TimeSinceGuidingStarted(); @@ -1526,6 +1527,7 @@ void Guider::UpdateGuideState(usImage *pImage, bool bStopping) case STATE_STOP: break; } + frameStarPositions.send(); } catch (const wxString& Msg) { diff --git a/src/guider.h b/src/guider.h index 67b3cea73..041b1272b 100644 --- a/src/guider.h +++ b/src/guider.h @@ -105,6 +105,7 @@ struct LockPosShiftParams }; class DefectMap; +class MultiStarReport; /* * The Guider class is responsible for running the state machine @@ -205,6 +206,7 @@ class Guider : public wxWindow bool PaintHelper(wxAutoBufferedPaintDCBase& dc, wxMemoryDC& memDC); void SetState(GUIDER_STATE newState); void UpdateCurrentDistance(double distance, double distanceRA); + virtual void reportSecondaryStarsAsUnused(MultiStarReport *multiStarReport) = 0; void ToggleBookmark(const wxRealPoint& pt); @@ -297,7 +299,8 @@ class Guider : public wxWindow virtual void InvalidateCurrentPosition(bool fullReset = false) = 0; private: - virtual bool UpdateCurrentPosition(const usImage *pImage, GuiderOffset *ofs, FrameDroppedInfo *errorInfo) = 0; + virtual bool UpdateCurrentPosition(const usImage *pImage, GuiderOffset *ofs, FrameDroppedInfo *errorInfo, + MultiStarReport *multiStarReport) = 0; virtual bool SetCurrentPosition(const usImage *pImage, const PHD_Point& position) = 0; public: diff --git a/src/guider_multistar.cpp b/src/guider_multistar.cpp index 3c6857aa2..5f7f2755b 100644 --- a/src/guider_multistar.cpp +++ b/src/guider_multistar.cpp @@ -41,6 +41,7 @@ */ #include "phd.h" +#include "event_server.h" #include #include @@ -716,8 +717,25 @@ static void AppendStarUse(wxString& secondaryInfo, int starNum, double dX, doubl secondaryInfo += wxString::Format("[#%d %0.2f,%0.2f,%0.2f,%s] ", starNum, dX, dY, weight, flag); } +void GuiderMultiStar::reportSecondaryStarsAsUnused(MultiStarReport *multiStarReport) +{ + if (!m_multiStarMode) + { + return; + } + auto pGS = m_guideStars.begin(); + if (pGS == m_guideStars.end()) + { + return; + } + for (pGS++; pGS != m_guideStars.end(); ++pGS) + { + multiStarReport->addStar(MultiStarReport::Item::unused(*pGS)); + } +} + // Use secondary stars to refine Offset value if appropriate. Return of true means offset has been adjusted -bool GuiderMultiStar::RefineOffset(const usImage *pImage, GuiderOffset *pOffset) +bool GuiderMultiStar::RefineOffset(const usImage *pImage, GuiderOffset *pOffset, MultiStarReport *multiStarReport) { double primaryDistance; double secondaryDistance; @@ -778,6 +796,8 @@ bool GuiderMultiStar::RefineOffset(const usImage *pImage, GuiderOffset *pOffset) pGS->referencePoint.X = pGS->X; pGS->referencePoint.Y = pGS->Y; pGS->wasLost = false; + + multiStarReport->addStar(MultiStarReport::Item::healthy(*pGS)); ++pGS; } else @@ -785,6 +805,9 @@ bool GuiderMultiStar::RefineOffset(const usImage *pImage, GuiderOffset *pOffset) // Don't need to update reference point, lost star will continue to use the // offsetFromPrimary location for possible recovery pGS->wasLost = true; + + multiStarReport->addStar( + MultiStarReport::Item::unhealthy(*pGS, MultiStarReport::Item::Lost)); ++pGS; } } @@ -796,13 +819,22 @@ bool GuiderMultiStar::RefineOffset(const usImage *pImage, GuiderOffset *pOffset) else m_stabilizing = true; // get some data for primary star movement + multiStarReport->setStabilizing(m_stabilizing); + if (!m_stabilizing && m_guideStars.size() > 1 && (sumX != 0 || sumY != 0)) { wxString secondaryInfo = "MultiStar: "; for (auto pGS = m_guideStars.begin() + 1; pGS != m_guideStars.end();) { if (m_starsUsed >= m_maxStars || m_guideStars.size() == 1) + { + while (pGS != m_guideStars.end()) + { + multiStarReport->addStar(MultiStarReport::Item::unused(*pGS)); + ++pGS; + } break; + } bool found = false; if (pGS->wasLost) { @@ -834,6 +866,8 @@ bool GuiderMultiStar::RefineOffset(const usImage *pImage, GuiderOffset *pOffset) if (pGS->zeroCount == 5) { + multiStarReport->addStar( + MultiStarReport::Item::unhealthy(*pGS, MultiStarReport::Item::ZeroDelta)); AppendStarUse(secondaryInfo, Iter_Inx(pGS), 0, 0, 0, "DZ"); pGS = m_guideStars.erase(pGS); erasures = true; @@ -846,6 +880,9 @@ bool GuiderMultiStar::RefineOffset(const usImage *pImage, GuiderOffset *pOffset) { if (++pGS->missCount > 10) { + multiStarReport->addStar( + MultiStarReport::Item::unhealthy(*pGS, MultiStarReport::Item::Reset)); + // Reset the reference point to wherever it is now pGS->referencePoint.X = pGS->X; pGS->referencePoint.Y = pGS->Y; @@ -853,9 +890,15 @@ bool GuiderMultiStar::RefineOffset(const usImage *pImage, GuiderOffset *pOffset) AppendStarUse(secondaryInfo, Iter_Inx(pGS), dX, dY, 0, "R"); } else + { + multiStarReport->addStar( + MultiStarReport::Item::unhealthy(*pGS, MultiStarReport::Item::Missed(pGS->missCount))); AppendStarUse(secondaryInfo, Iter_Inx(pGS), dX, dY, 0, "M" + std::to_string(pGS->missCount)); + } + ++pGS; + continue; } else if (pGS->missCount > 0) @@ -871,10 +914,12 @@ bool GuiderMultiStar::RefineOffset(const usImage *pImage, GuiderOffset *pOffset) averaged = true; validStars++; + multiStarReport->addStar(MultiStarReport::Item::healthy(*pGS)); AppendStarUse(secondaryInfo, Iter_Inx(pGS), dX, dY, wt, "U"); } else // exactly zero on both axes, probably a hot pixel, drop it { + multiStarReport->addStar(MultiStarReport::Item::unhealthy(*pGS, MultiStarReport::Item::ZeroDelta)); AppendStarUse(secondaryInfo, Iter_Inx(pGS), 0, 0, 0, "DZ"); pGS = m_guideStars.erase(pGS); erasures = true; @@ -883,6 +928,8 @@ bool GuiderMultiStar::RefineOffset(const usImage *pImage, GuiderOffset *pOffset) else { // star not found in its search region + multiStarReport->addStar(MultiStarReport::Item::unhealthy(*pGS, MultiStarReport::Item::Lost)); + AppendStarUse(secondaryInfo, Iter_Inx(pGS), 0, 0, 0, "L"); pGS->wasLost = true; } @@ -901,6 +948,8 @@ bool GuiderMultiStar::RefineOffset(const usImage *pImage, GuiderOffset *pOffset) { pOffset->cameraOfs.X = sumX; pOffset->cameraOfs.Y = sumY; + multiStarReport->setRefined(true); + refined = true; } Debug.Write(wxString::Format("%s, %d included, MultiStar: {%0.2f, %0.2f}, one-star: {%0.2f, %0.2f}\n", @@ -908,6 +957,14 @@ bool GuiderMultiStar::RefineOffset(const usImage *pImage, GuiderOffset *pOffset) origOffset.cameraOfs.X, origOffset.cameraOfs.Y)); } } + else + { + reportSecondaryStarsAsUnused(multiStarReport); + } + } + else + { + reportSecondaryStarsAsUnused(multiStarReport); } } catch (const wxString& msg) @@ -922,11 +979,13 @@ bool GuiderMultiStar::RefineOffset(const usImage *pImage, GuiderOffset *pOffset) static DistanceChecker s_distanceChecker; -bool GuiderMultiStar::UpdateCurrentPosition(const usImage *pImage, GuiderOffset *ofs, FrameDroppedInfo *errorInfo) +bool GuiderMultiStar::UpdateCurrentPosition(const usImage *pImage, GuiderOffset *ofs, FrameDroppedInfo *errorInfo, + MultiStarReport *multiStarReport) { if (!m_primaryStar.IsValid() && m_primaryStar.X == 0.0 && m_primaryStar.Y == 0.0) { Debug.Write("UpdateCurrentPosition: no star selected\n"); + reportSecondaryStarsAsUnused(multiStarReport); errorInfo->starError = Star::STAR_ERROR; errorInfo->starMass = 0.0; errorInfo->starSNR = 0.0; @@ -945,6 +1004,8 @@ bool GuiderMultiStar::UpdateCurrentPosition(const usImage *pImage, GuiderOffset if (!newStar.Find(pImage, m_searchRegion, pFrame->GetStarFindMode(), GetMinStarHFD(), GetMaxStarHFD(), pCamera->GetSaturationADU(), Star::FIND_LOGGING_VERBOSE)) { + multiStarReport->addStar(MultiStarReport::Item::unhealthy(newStar, MultiStarReport::Item::Lost)); + reportSecondaryStarsAsUnused(multiStarReport); errorInfo->starError = newStar.GetError(); errorInfo->starMass = 0.0; errorInfo->starSNR = 0.0; @@ -969,6 +1030,9 @@ bool GuiderMultiStar::UpdateCurrentPosition(const usImage *pImage, GuiderOffset double limits[4]; if (m_massChecker->CheckMass(newStar.Mass, m_massChangeThreshold, limits)) { + multiStarReport->addStar(MultiStarReport::Item::unhealthy(newStar, MultiStarReport::Item::InvalidMass)); + reportSecondaryStarsAsUnused(multiStarReport); + m_primaryStar.SetError(Star::STAR_MASSCHANGE); errorInfo->starError = Star::STAR_MASSCHANGE; errorInfo->starMass = newStar.Mass; @@ -1007,6 +1071,9 @@ bool GuiderMultiStar::UpdateCurrentPosition(const usImage *pImage, GuiderOffset if (!s_distanceChecker.CheckDistance(distance, raOnly, tolerance)) { + multiStarReport->addStar(MultiStarReport::Item::unhealthy(newStar, MultiStarReport::Item::TooFar)); + reportSecondaryStarsAsUnused(multiStarReport); + m_primaryStar.SetError(Star::STAR_ERROR); errorInfo->starError = Star::STAR_ERROR; errorInfo->starMass = newStar.Mass; @@ -1020,6 +1087,7 @@ bool GuiderMultiStar::UpdateCurrentPosition(const usImage *pImage, GuiderOffset throw THROW_INFO("CheckDistance error"); } + multiStarReport->addStar(MultiStarReport::Item::healthy(newStar)); ImageLogger::LogImage(pImage, distance); // update the star position, mass, etc. @@ -1031,17 +1099,24 @@ bool GuiderMultiStar::UpdateCurrentPosition(const usImage *pImage, GuiderOffset ofs->cameraOfs = m_primaryStar - lockPos; if (m_multiStarMode && m_guideStars.size() > 1) { - if (RefineOffset(pImage, ofs)) + if (RefineOffset(pImage, ofs, multiStarReport)) distance = hypot(ofs->cameraOfs.X, ofs->cameraOfs.Y); // Distance is reported to server clients } else + { m_starsUsed = 1; + reportSecondaryStarsAsUnused(multiStarReport); + } if (pMount && pMount->IsCalibrated()) pMount->TransformCameraCoordinatesToMountCoordinates(ofs->cameraOfs, ofs->mountOfs, true); double distanceRA = ofs->mountOfs.IsValid() ? fabs(ofs->mountOfs.X) : 0.; UpdateCurrentDistance(distance, distanceRA); } + else + { + reportSecondaryStarsAsUnused(multiStarReport); + } pFrame->pProfile->UpdateData(pImage, m_primaryStar.X, m_primaryStar.Y); diff --git a/src/guider_multistar.h b/src/guider_multistar.h index 6c162348c..3f24a7241 100644 --- a/src/guider_multistar.h +++ b/src/guider_multistar.h @@ -47,6 +47,7 @@ class MassChecker; class GuiderMultiStar; class GuiderConfigDialogCtrlSet; +class MultiStarReport; class GuiderMultiStarConfigDialogCtrlSet : public GuiderConfigDialogCtrlSet { @@ -112,7 +113,7 @@ class GuiderMultiStar : public Guider bool SetMassChangeThreshold(double starMassChangeThreshold); bool SetTolerateJumps(bool enable, double threshold); bool SetSearchRegion(int searchRegion); - bool RefineOffset(const usImage *pImage, GuiderOffset *pOffset); + bool RefineOffset(const usImage *pImage, GuiderOffset *pOffset, MultiStarReport *multiStarReport); friend class GuiderMultiStarConfigDialogPane; friend class GuiderMultiStarConfigDialogCtrlSet; @@ -146,8 +147,10 @@ class GuiderMultiStar : public Guider bool IsValidLockPosition(const PHD_Point& pt) final; bool IsValidSecondaryStarPosition(const PHD_Point& pt) final; void InvalidateCurrentPosition(bool fullReset = false) final; - bool UpdateCurrentPosition(const usImage *pImage, GuiderOffset *ofs, FrameDroppedInfo *errorInfo) final; + bool UpdateCurrentPosition(const usImage *pImage, GuiderOffset *ofs, FrameDroppedInfo *errorInfo, + MultiStarReport *multiStarReport) final; bool SetCurrentPosition(const usImage *pImage, const PHD_Point& position) final; + void reportSecondaryStarsAsUnused(MultiStarReport *multiStarReport) final; void OnLClick(wxMouseEvent& evt); diff --git a/src/image_math.cpp b/src/image_math.cpp index dbe0de9f5..7d46c6a7e 100644 --- a/src/image_math.cpp +++ b/src/image_math.cpp @@ -40,6 +40,7 @@ #include #include +#include int dbl_sort_func(double *first, double *second) { diff --git a/src/log_uploader.cpp b/src/log_uploader.cpp index ade0cbaba..90a4ca179 100644 --- a/src/log_uploader.cpp +++ b/src/log_uploader.cpp @@ -34,6 +34,7 @@ #include "log_uploader.h" #include "phd.h" +#include "json_parser.h" #include #include diff --git a/src/mount.cpp b/src/mount.cpp index 3e20589b4..df2395cce 100644 --- a/src/mount.cpp +++ b/src/mount.cpp @@ -34,6 +34,7 @@ */ #include "phd.h" +#include "event_server.h" #include "backlash_comp.h" #include "guiding_assistant.h" #include "gaussian_process_guider.h" diff --git a/src/myframe.cpp b/src/myframe.cpp index 6c06038b3..496302f5a 100644 --- a/src/myframe.cpp +++ b/src/myframe.cpp @@ -36,6 +36,7 @@ #include "phd.h" +#include "event_server.h" #include "aui_controls.h" #include "comet_tool.h" #include "config_indi.h" diff --git a/src/myframe_events.cpp b/src/myframe_events.cpp index 892c9454a..ed5288447 100644 --- a/src/myframe_events.cpp +++ b/src/myframe_events.cpp @@ -34,6 +34,7 @@ #include "phd.h" +#include "event_server.h" #include "about_dialog.h" #include "aui_controls.h" #include "camcal_import_dialog.h" diff --git a/src/phd.h b/src/phd.h index e5af89d6e..6eae4fda3 100644 --- a/src/phd.h +++ b/src/phd.h @@ -183,7 +183,6 @@ WX_DEFINE_ARRAY_DOUBLE(double, ArrayOfDbl); #include "myframe.h" #include "debuglog.h" #include "worker_thread.h" -#include "event_server.h" #include "confirm_dialog.h" #include "phdcontrol.h" #include "runinbg.h" diff --git a/src/phdcontrol.cpp b/src/phdcontrol.cpp index 8a817a2a8..f1825976f 100644 --- a/src/phdcontrol.cpp +++ b/src/phdcontrol.cpp @@ -33,7 +33,7 @@ */ #include "phd.h" - +#include "event_server.h" enum State { STATE_IDLE = 0, diff --git a/src/scope.cpp b/src/scope.cpp index 7e280132b..6622dafb0 100644 --- a/src/scope.cpp +++ b/src/scope.cpp @@ -32,6 +32,7 @@ * */ #include "phd.h" +#include "event_server.h" #include "backlash_comp.h" #include "calreview_dialog.h" diff --git a/src/socket_server.cpp b/src/socket_server.cpp index 6967b0cd0..221c3739c 100644 --- a/src/socket_server.cpp +++ b/src/socket_server.cpp @@ -33,6 +33,7 @@ */ #include "phd.h" +#include "event_server.h" #include "socket_server.h" #include "gear_simulator.h" diff --git a/src/star.cpp b/src/star.cpp index c01dce06f..b198afee2 100644 --- a/src/star.cpp +++ b/src/star.cpp @@ -36,6 +36,7 @@ */ #include "phd.h" +#include "event_server.h" #include Star::Star() diff --git a/src/stepguider.cpp b/src/stepguider.cpp index a6c7fde26..fe3ddcb2d 100644 --- a/src/stepguider.cpp +++ b/src/stepguider.cpp @@ -34,6 +34,7 @@ */ #include "phd.h" +#include "event_server.h" #include "gear_simulator.h" #include "image_math.h" #include "socket_server.h"