BOOL VLDeclAddWayPoint(PDeviceDescriptor_t d, const WAYPOINT *wp){ if (nturnpoints == 0) { TCHAR2usascii(wp->Name, vl.declaration.task.startpoint.name, 7); vl.declaration.task.startpoint.name[6] ='\0'; vl.declaration.task.startpoint.lon = wp->Longitude; vl.declaration.task.startpoint.lat = wp->Latitude; nturnpoints++; } else { TCHAR2usascii(wp->Name, vl.declaration.task.turnpoints[nturnpoints-1].name, 7); vl.declaration.task.turnpoints[nturnpoints-1].name[6]='\0'; vl.declaration.task.turnpoints[nturnpoints-1].lon = wp->Longitude; vl.declaration.task.turnpoints[nturnpoints-1].lat = wp->Latitude; nturnpoints++; } TCHAR2usascii(wp->Name, vl.declaration.task.finishpoint.name, 7); vl.declaration.task.finishpoint.name[6]='\0'; vl.declaration.task.finishpoint.lon = wp->Longitude; vl.declaration.task.finishpoint.lat = wp->Latitude; return(TRUE); }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /// Converts TCHAR[] string into US-ASCII string with characters safe for /// writing to LX devices. /// /// Characters are converted into their most similar representation /// in ASCII. Nonconvertable characters are replaced by '?'. /// /// Output string will always be terminated by '\0'. /// /// @param input input string (must be terminated with '\0') /// @param outSize output buffer size /// @param output output buffer /// /// @retval true all characters copied /// @retval false some characters could not be copied due to buffer size /// //static bool DevLXNano::Wide2LxAscii(const TCHAR* input, int outSize, char* output) { if (outSize == 0) return(false); int res = TCHAR2usascii(input, output, outSize); // replace all non-ascii characters with '?' - LX Colibri is very sensitive // on non-ascii chars - the electronic seal can be broken // (unicode2usascii() should be enough, but to be sure that someone has not // incorrectly changed unicode2usascii()) output--; while (*++output != '\0') { if (*output < 32 || *output > 126) *output = '?'; } return(res >= 0); } // Wide2LxAscii()
/** * @brief Sends task declaration * * @param d Device handle * @param decl Task declaration data * @param errBufSize The size of the buffer for error string * @param errBuf The buffer for error string * * @return Operation status */ bool CDevIMI::DeclarationWrite(PDeviceDescriptor_t d, const Declaration_t &decl, unsigned errBufSize, TCHAR errBuf[]) { if(!_connected) { // LKTOKEN _@M1411_ = "Device not connected!" _sntprintf(errBuf, errBufSize, _T("%s"), gettext(_T("_@M1411_"))); return false; } TDeclaration imiDecl; memset(&imiDecl, 0, sizeof(imiDecl)); // idecl.date ignored - will be set by FR TCHAR2usascii(decl.PilotName, imiDecl.header.plt, sizeof(imiDecl.header.plt)); // decl.header.db1Year = year; decl.header.db1Month = month; decl.header.db1Day = day; TCHAR2usascii(decl.AircraftType, imiDecl.header.gty, sizeof(imiDecl.header.gty)); TCHAR2usascii(decl.AircraftRego, imiDecl.header.gid, sizeof(imiDecl.header.gid)); TCHAR2usascii(decl.CompetitionID, imiDecl.header.cid, sizeof(imiDecl.header.cid)); TCHAR2usascii(decl.CompetitionClass, imiDecl.header.ccl, sizeof(imiDecl.header.ccl)); // strncpy(decl.header.clb, idecl.clb, sizeof(decl.header.clb)); // strncpy(decl.header.sit, idecl.sit, sizeof(decl.header.sit)); // strncpy(decl.header.cm2, idecl.cm2, sizeof(decl.header.cm2)); // decl.header.db2Year = year; decl.header.db2Month = month; decl.header.db2Day = day; TCHAR tskName[IMIDECL_TASK_NAME_LENGTH]; TaskFileName(IMIDECL_TASK_NAME_LENGTH, tskName); TCHAR2usascii(tskName, imiDecl.header.tskName, sizeof(imiDecl.header.tskName)); // decl.header.tskYear = year; decl.header.tskMonth = month; decl.header.tskDay = day; // decl.header.tskNumber = MIN(9999, idecl.tskNumber); IMIWaypoint(decl, 0, imiDecl.wp[0]); for(int i=0; i<decl.num_waypoints; i++) IMIWaypoint(decl, i + 1, imiDecl.wp[i + 1]); IMIWaypoint(decl, decl.num_waypoints + 1, imiDecl.wp[decl.num_waypoints + 1]); // send declaration for current task const TMsg *msg = SendRet(d, errBufSize, errBuf, MSG_DECLARATION, &imiDecl, sizeof(imiDecl), MSG_ACK_SUCCESS, 0, static_cast<IMIBYTE>(-1)); if(!msg && errBuf[0] == '\0') { // LKTOKEN _@M1415_ = "Declaration not accepted!" _sntprintf(errBuf, errBufSize, _T("%s"), gettext(_T("_@M1415_"))); } return msg; }
/** * @brief Sets data in IMI Waypoint structure * * @param decl LK task declaration * @param imiIdx The index of IMI waypoint to set * @param imiWp IMI waypoint structure to set */ void CDevIMI::IMIWaypoint(const Declaration_t &decl, unsigned imiIdx, TWaypoint &imiWp) { unsigned idx = imiIdx == 0 ? 0 : (imiIdx == (unsigned)decl.num_waypoints + 1 ? imiIdx - 2 : imiIdx - 1); const WAYPOINT &wp = *decl.waypoint[idx]; // set name TCHAR2usascii(wp.Name, imiWp.name, sizeof(imiWp.name)); // set latitude TAngle a; double angle = wp.Latitude; if((a.sign = (angle < 0) ? 1 : 0) != 0) angle *= -1; a.degrees = static_cast<IMIDWORD>(angle); a.milliminutes = static_cast<IMIDWORD>((angle - a.degrees) * 60 * 1000); imiWp.lat = a.value; // set longitude angle = wp.Longitude; if((a.sign = (angle < 0) ? 1 : 0) != 0) angle *= -1; a.degrees = static_cast<IMIDWORD>(angle); a.milliminutes = static_cast<IMIDWORD>((angle - a.degrees) * 60 * 1000); imiWp.lon = a.value; // TAKEOFF and LANDING do not have OZs if(imiIdx == 0 || imiIdx == (unsigned)decl.num_waypoints + 1) return; // set observation zones if(imiIdx == 1) { // START imiWp.oz.style = 3; switch(StartLine) { case 0: // cylinder imiWp.oz.A1 = 1800; break; case 1: // line imiWp.oz.line_only = 1; break; case 2: // fai sector imiWp.oz.A1 = 450; break; } imiWp.oz.R1 = std::min((DWORD)250000, StartRadius); } else if(imiIdx == (unsigned)decl.num_waypoints) { // FINISH imiWp.oz.style = 4; switch(FinishLine) { case 0: // cylinder imiWp.oz.A1 = 1800; break; case 1: // line imiWp.oz.line_only = 1; break; case 2: // fai sector imiWp.oz.A1 = 450; break; } imiWp.oz.R1 = std::min((DWORD)250000, FinishRadius); } else { // TPs if(AATEnabled) { imiWp.oz.style = 1; switch(Task[idx].AATType) { case CIRCLE: imiWp.oz.A1 = 1800; imiWp.oz.R1 = std::min(250000, (int)Task[idx].AATCircleRadius); break; case SECTOR: imiWp.oz.A1 = ((int)(360 + Task[idx].AATFinishRadial - Task[idx].AATStartRadial) % 360) * 10 / 2; imiWp.oz.A12 = ((int)(Task[idx].AATStartRadial * 10) + 1800 + imiWp.oz.A1) % 3600; imiWp.oz.R1 = std::min(250000, (int)Task[idx].AATSectorRadius); break; } } else { imiWp.oz.style = 2; switch(SectorType) { case 0: // cylinder imiWp.oz.A1 = 1800; imiWp.oz.R1 = std::min((DWORD)250000, SectorRadius); break; case 1: // sector imiWp.oz.A1 = 450; imiWp.oz.R1 = std::min((DWORD)250000, SectorRadius); break; case 2: // German DAe 0.5/10 imiWp.oz.A1 = 450; imiWp.oz.R1 = 10000; imiWp.oz.A2 = 1800; imiWp.oz.R2 = 500; break; } } } // other unused data imiWp.oz.maxAlt = 0; imiWp.oz.reduce = 0; imiWp.oz.move = 0; }
BOOL VLDeclare(PDeviceDescriptor_t d, Declaration_t *decl, unsigned errBufferLen, TCHAR errBuffer[]) { vl.set_device(d); nturnpoints = 0; const unsigned BUFF_LEN = 128; TCHAR buffer[BUFF_LEN]; int err = VLA_ERR_NOERR; // LKTOKEN _@M1400_ = "Task declaration" // LKTOKEN _@M1404_ = "Opening connection" _sntprintf(buffer, BUFF_LEN, _T("%s: %s..."), MsgToken(1400), MsgToken(1404)); CreateProgressDialog(buffer); if((err = vl.open(1, 20, 1, 38400L)) != VLA_ERR_NOERR) { // LKTOKEN _@M1411_ = "Device not connected!" _tcsncpy(errBuffer, MsgToken(1411), errBufferLen); return FALSE; } // LKTOKEN _@M1400_ = "Task declaration" // LKTOKEN _@M1405_ = "Testing connection" _sntprintf(buffer, BUFF_LEN, _T("%s: %s..."), MsgToken(1400), MsgToken(1405)); CreateProgressDialog(buffer); if((err = vl.read_info()) != VLA_ERR_NOERR) { // LKTOKEN _@M1414_ = "Device not responsive!" _tcsncpy(errBuffer, MsgToken(1414), errBufferLen); return FALSE; } TCHAR2usascii(decl->PilotName, vl.declaration.flightinfo.pilot, 66); vl.declaration.flightinfo.pilot[64]='\0'; TCHAR2usascii(decl->AircraftRego, vl.declaration.flightinfo.gliderid, 8); vl.declaration.flightinfo.gliderid[7]='\0'; TCHAR2usascii(decl->AircraftType, vl.declaration.flightinfo.glidertype, 13); vl.declaration.flightinfo.glidertype[12]='\0'; TCHAR2usascii(decl->CompetitionID, vl.declaration.flightinfo.competitionid, 4); vl.declaration.flightinfo.competitionid[3]='\0'; // BUGFIX 100331 TCHAR2usascii(decl->CompetitionClass, vl.declaration.flightinfo.competitionclass, 13); vl.declaration.flightinfo.competitionclass[12]='\0'; // BUGFIX 100331 if (ValidWayPoint(HomeWaypoint)) { TCHAR2usascii(WayPointList[HomeWaypoint].Name, vl.declaration.flightinfo.homepoint.name, 7); vl.declaration.flightinfo.homepoint.name[6]='\0'; // BUGFIX 100331 vl.declaration.flightinfo.homepoint.lon = WayPointList[HomeWaypoint].Longitude; vl.declaration.flightinfo.homepoint.lat = WayPointList[HomeWaypoint].Latitude; } int i; for (i = 0; i < decl->num_waypoints; i++) VLDeclAddWayPoint(d, decl->waypoint[i]); vl.declaration.task.nturnpoints = max(min(nturnpoints-2, 12), 0); LockTaskData(); // start.. switch(StartLine) { case 0: // cylinder vl.declaration.task.startpoint.oztyp = VLAPI_DATA::DCLWPT::OZTYP_CYLSKT; vl.declaration.task.startpoint.lw = min(1500,(int)StartRadius); vl.declaration.task.startpoint.rz = min(1500,(int)StartRadius); vl.declaration.task.startpoint.rs = 0; break; case 1: // line vl.declaration.task.startpoint.oztyp = VLAPI_DATA::DCLWPT::OZTYP_LINE; vl.declaration.task.startpoint.lw = StartRadius * 2; vl.declaration.task.startpoint.rs = 0; vl.declaration.task.startpoint.rz = 0; break; case 2: // fai sector vl.declaration.task.startpoint.oztyp = VLAPI_DATA::DCLWPT::OZTYP_CYLSKT; vl.declaration.task.startpoint.lw = min(15000,(int)StartRadius); vl.declaration.task.startpoint.rz = 0; vl.declaration.task.startpoint.rs = min(15000,(int)StartRadius); break; } vl.declaration.task.startpoint.ws = 360; // rest of task... for (i=0; i<nturnpoints; i++) { // note this is for non-aat only! switch (SectorType) { case 0: // cylinder vl.declaration.task.turnpoints[i].oztyp = VLAPI_DATA::DCLWPT::OZTYP_CYLSKT; vl.declaration.task.turnpoints[i].rz = min(1500,(int)SectorRadius); vl.declaration.task.turnpoints[i].rs = 0; vl.declaration.task.turnpoints[i].lw = 0; break; case 1: // sector vl.declaration.task.turnpoints[i].oztyp = VLAPI_DATA::DCLWPT::OZTYP_CYLSKT; vl.declaration.task.turnpoints[i].rz = 0; vl.declaration.task.turnpoints[i].rs = min(15000,(int)SectorRadius); vl.declaration.task.turnpoints[i].lw = 0; break; case 2: // German DAe 0.5/10 vl.declaration.task.turnpoints[i].oztyp = VLAPI_DATA::DCLWPT::OZTYP_CYLSKT; vl.declaration.task.turnpoints[i].rz = 500; vl.declaration.task.turnpoints[i].rs = 10000; vl.declaration.task.turnpoints[i].lw = 0; break; }; vl.declaration.task.turnpoints[i].ws = 360; // auto direction } // Finish switch(FinishLine) { case 0: // cylinder vl.declaration.task.finishpoint.oztyp = VLAPI_DATA::DCLWPT::OZTYP_CYLSKT; vl.declaration.task.finishpoint.lw = min(1500,(int)FinishRadius); vl.declaration.task.finishpoint.rz = min(1500,(int)FinishRadius); vl.declaration.task.finishpoint.rs = 0; break; case 1: // line vl.declaration.task.finishpoint.oztyp = VLAPI_DATA::DCLWPT::OZTYP_LINE; vl.declaration.task.finishpoint.lw = FinishRadius*2; vl.declaration.task.finishpoint.rz = 0; vl.declaration.task.finishpoint.rs = 0; break; case 2: // fai sector vl.declaration.task.finishpoint.oztyp = VLAPI_DATA::DCLWPT::OZTYP_CYLSKT; vl.declaration.task.finishpoint.lw = min(15000,(int)FinishRadius); vl.declaration.task.finishpoint.rz = 0; vl.declaration.task.finishpoint.rs = min(15000,(int)FinishRadius); break; } vl.declaration.task.finishpoint.ws = 360; UnlockTaskData(); // LKTOKEN _@M1400_ = "Task declaration" // LKTOKEN _@M1403_ = "Sending declaration" _sntprintf(buffer, BUFF_LEN, _T("%s: %s..."), MsgToken(1400), MsgToken(1403)); CreateProgressDialog(buffer); if((err = vl.write_db_and_declaration()) != VLA_ERR_NOERR) { // LKTOKEN _@M1415_ = "Declaration not accepted!" _tcsncpy(errBuffer, MsgToken(1415), errBufferLen); } // LKTOKEN _@M1400_ = "Task declaration" // LKTOKEN _@M1406_ = "Closing connection" _sntprintf(buffer, BUFF_LEN, _T("%s: %s..."), MsgToken(1400), MsgToken(1406)); CreateProgressDialog(buffer); vl.close(1); return err == VLA_ERR_NOERR; }