using System;
using System.Collections.Generic;
using System.Reactive.Subjects;
using System.Text;
using System.Runtime.InteropServices;
using System.Collections; // hashs
using System.Diagnostics; // stopwatch
using System.Reflection;
using System.Reflection.Emit;
using System.IO;
using System.Drawing;
using System.Threading;
using ArdupilotMega.Controls;
using System.ComponentModel;
using log4net;
using ArdupilotMega.Comms;
using ArdupilotMega.Utilities;
using System.Windows.Forms;
namespace ArdupilotMega
{
public partial class MAVLink
{
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public ICommsSerial BaseStream { get; set; }
public event EventHandler ParamListChanged;
private const double CONNECT_TIMEOUT_SECONDS = 30;
///
/// progress form to handle connect and param requests
///
ProgressReporterDialogue frmProgressReporter;
///
/// used for outbound packet sending
///
byte packetcount = 0;
///
/// mavlink remote sysid
///
public byte sysid { get; set; }
///
/// mavlink remove compid
///
public byte compid { get; set; }
///
/// storage for whole paramater list
///
public Hashtable param { get; set; }
///
/// storage of a previous packet recevied of a specific type
///
public byte[][] packets { get; set; }
///
/// used to calc packets per second on any single message type - used for stream rate comparaison
///
public double[] packetspersecond { get; set; }
///
/// time last seen a packet of a type
///
DateTime[] packetspersecondbuild = new DateTime[256];
private readonly Subject _bytesReceivedSubj = new Subject();
private readonly Subject _bytesSentSubj = new Subject();
///
/// Observable of the count of bytes received, notified when the bytes themselves are received
///
public IObservable BytesReceived { get { return _bytesReceivedSubj; } }
///
/// Observable of the count of bytes sent, notified when the bytes themselves are received
///
public IObservable BytesSent { get { return _bytesSentSubj; } }
///
/// Observable of the count of packets skipped (on reception),
/// calculated from periods where received packet sequence is not
/// contiguous
///
public Subject WhenPacketLost { get; set; }
public Subject WhenPacketReceived { get; set; }
///
/// used as a serial port write lock
///
volatile object objlock = new object();
///
/// used for a readlock on readpacket
///
volatile object readlock = new object();
///
/// time seen of last mavlink packet
///
public DateTime lastvalidpacket { get; set; }
///
/// old log support
///
bool oldlogformat = false;
///
/// mavlink version
///
byte mavlinkversion = 0;
///
/// mavlink ap type
///
public MAV_TYPE aptype { get; set; }
public MAV_AUTOPILOT apname { get; set; }
///
/// used as a snapshot of what is loaded on the ap atm. - derived from the stream
///
public Dictionary wps = new Dictionary();
///
/// Store the guided mode wp location
///
public mavlink_mission_item_t GuidedMode = new mavlink_mission_item_t();
///
/// turns on console packet display
///
public bool debugmavlink { get; set; }
///
/// enabled read from file mode
///
public bool logreadmode { get; set; }
public DateTime lastlogread { get; set; }
public BinaryReader logplaybackfile { get; set; }
public BinaryWriter logfile { get; set; }
public BinaryWriter rawlogfile { get; set; }
int bps1 = 0;
int bps2 = 0;
public int bps { get; set; }
public DateTime bpstime { get; set; }
int recvpacketcount = 0;
float synclost;
float packetslost = 0;
float packetsnotlost = 0;
DateTime packetlosttimer = DateTime.Now;
public MAVLink()
{
// init fields
this.BaseStream = new SerialPort();
this.packetcount = 0;
this.sysid = 0;
this.compid = 0;
this.param = new Hashtable();
this.packets = new byte[0x100][];
this.packetspersecond = new double[0x100];
this.packetspersecondbuild = new DateTime[0x100];
this._bytesReceivedSubj = new Subject();
this._bytesSentSubj = new Subject();
this.WhenPacketLost = new Subject();
this.WhenPacketReceived = new Subject();
this.readlock = new object();
this.lastvalidpacket = DateTime.Now;
this.oldlogformat = false;
this.mavlinkversion = 0;
this.aptype = 0;
this.apname = 0;
this.debugmavlink = false;
this.logreadmode = false;
this.lastlogread = DateTime.MinValue;
this.logplaybackfile = null;
this.logfile = null;
this.rawlogfile = null;
this.bps1 = 0;
this.bps2 = 0;
this.bps = 0;
this.bpstime = DateTime.Now;
this.recvpacketcount = 0;
this.packetslost = 0f;
this.packetsnotlost = 0f;
this.packetlosttimer = DateTime.Now;
this.lastbad = new byte[2];
}
public void Close()
{
try
{
logfile.Close();
}
catch { }
try
{
rawlogfile.Close();
}
catch { }
try
{
logplaybackfile.Close();
}
catch { }
BaseStream.Close();
}
public void Open()
{
Open(false);
}
public void Open(bool getparams)
{
if (BaseStream.IsOpen)
return;
frmProgressReporter = new ProgressReporterDialogue
{
StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen,
Text = "Connecting Mavlink"
};
if (getparams)
{
frmProgressReporter.DoWork += FrmProgressReporterDoWorkAndParams;
}
else
{
frmProgressReporter.DoWork += FrmProgressReporterDoWorkNOParams;
}
frmProgressReporter.UpdateProgressAndStatus(-1, "Mavlink Connecting...");
ThemeManager.ApplyThemeTo(frmProgressReporter);
frmProgressReporter.RunBackgroundOperationAsync();
if (ParamListChanged != null)
{
ParamListChanged(this,null);
}
}
void FrmProgressReporterDoWorkAndParams(object sender, ProgressWorkerEventArgs e)
{
OpenBg(true, e);
}
void FrmProgressReporterDoWorkNOParams(object sender, ProgressWorkerEventArgs e)
{
OpenBg(false, e);
}
private void OpenBg(bool getparams, ProgressWorkerEventArgs progressWorkerEventArgs)
{
frmProgressReporter.UpdateProgressAndStatus(-1, "Mavlink Connecting...");
MainV2.giveComport = true;
// allow settings to settle - previous dtr
System.Threading.Thread.Sleep(500);
// reset
sysid = 0;
compid = 0;
param = new Hashtable();
packets.Initialize();
bool hbseen = false;
try
{
BaseStream.ReadBufferSize = 4 * 1024;
lock (objlock) // so we dont have random traffic
{
log.Info("Open port with " + BaseStream.PortName + " " + BaseStream.BaudRate);
BaseStream.Open();
BaseStream.DiscardInBuffer();
Thread.Sleep(1000);
}
byte[] buffer = new byte[0];
byte[] buffer1 = new byte[0];
DateTime start = DateTime.Now;
DateTime deadline = start.AddSeconds(CONNECT_TIMEOUT_SECONDS);
var countDown = new System.Timers.Timer { Interval = 1000, AutoReset = false };
countDown.Elapsed += (sender, e) =>
{
int secondsRemaining = (deadline - e.SignalTime).Seconds;
//if (Progress != null)
// Progress(-1, string.Format("Trying to connect.\nTimeout in {0}", secondsRemaining));
frmProgressReporter.UpdateProgressAndStatus(-1, string.Format("Trying to connect.\nTimeout in {0}", secondsRemaining));
if (secondsRemaining > 0) countDown.Start();
};
countDown.Start();
int count = 0;
while (true)
{
if (progressWorkerEventArgs.CancelRequested)
{
progressWorkerEventArgs.CancelAcknowledged = true;
countDown.Stop();
if (BaseStream.IsOpen)
BaseStream.Close();
MainV2.giveComport = false;
return;
}
// incase we are in setup mode
//BaseStream.WriteLine("planner\rgcs\r");
log.Info(DateTime.Now.Millisecond + " Start connect loop ");
if (lastbad[0] == '!' && lastbad[1] == 'G' || lastbad[0] == 'G' && lastbad[1] == '!') // waiting for gps lock
{
//if (Progress != null)
// Progress(-1, "Waiting for GPS detection..");
frmProgressReporter.UpdateProgressAndStatus(-1, "Waiting for GPS detection..");
deadline = deadline.AddSeconds(5); // each round is 1.1 seconds
}
if (DateTime.Now > deadline)
{
//if (Progress != null)
// Progress(-1, "No Heatbeat Packets");
countDown.Stop();
this.Close();
if (hbseen)
{
progressWorkerEventArgs.ErrorMessage = "Only 1 Heatbeat Received";
throw new Exception("Only 1 Mavlink Heartbeat Packets was read from this port - Verify your hardware is setup correctly\nAPM Planner waits for 2 valid heartbeat packets before connecting");
}
else
{
progressWorkerEventArgs.ErrorMessage = "No Heatbeat Packets Received";
throw new Exception("No Mavlink Heartbeat Packets where read from this port - Verify Baud Rate and setup\nAPM Planner waits for 2 valid heartbeat packets before connecting");
}
}
System.Threading.Thread.Sleep(1);
// incase we are in setup mode
//BaseStream.WriteLine("planner\rgcs\r");
// can see 2 heartbeat packets at any time, and will connect - was one after the other
if (buffer.Length == 0)
buffer = getHeartBeat();
// incase we are in setup mode
//BaseStream.WriteLine("planner\rgcs\r");
System.Threading.Thread.Sleep(1);
if (buffer1.Length == 0)
buffer1 = getHeartBeat();
if (buffer.Length > 0 || buffer1.Length > 0)
hbseen = true;
count++;
if (buffer.Length > 5 && buffer1.Length > 5 && buffer[3] == buffer1[3] && buffer[4] == buffer1[4])
{
mavlink_heartbeat_t hb = buffer.ByteArrayToStructure(6);
mavlinkversion = hb.mavlink_version;
aptype = (MAV_TYPE)hb.type;
apname = (MAV_AUTOPILOT)hb.autopilot;
setAPType();
sysid = buffer[3];
compid = buffer[4];
recvpacketcount = buffer[2];
log.InfoFormat("ID sys {0} comp {1} ver{2}", sysid, compid, mavlinkversion);
break;
}
}
countDown.Stop();
frmProgressReporter.UpdateProgressAndStatus(0, "Getting Params.. (sysid " + sysid + " compid " + compid + ") ");
if (getparams)
{
getParamListBG();
}
if (frmProgressReporter.doWorkArgs.CancelAcknowledged == true)
{
MainV2.giveComport = false;
if (BaseStream.IsOpen)
BaseStream.Close();
return;
}
}
catch (Exception e)
{
try
{
BaseStream.Close();
}
catch { }
MainV2.giveComport = false;
if (string.IsNullOrEmpty(progressWorkerEventArgs.ErrorMessage))
progressWorkerEventArgs.ErrorMessage = "Connect Failed";
throw e;
}
//frmProgressReporter.Close();
MainV2.giveComport = false;
frmProgressReporter.UpdateProgressAndStatus(100, "Done.");
log.Info("Done open " + sysid + " " + compid);
packetslost = 0;
synclost = 0;
}
byte[] getHeartBeat()
{
DateTime start = DateTime.Now;
while (true)
{
byte[] buffer = readPacket();
if (buffer.Length > 5)
{
//log.Info("getHB packet received: " + buffer.Length + " btr " + BaseStream.BytesToRead + " type " + buffer[5] );
if (buffer[5] == MAVLINK_MSG_ID_HEARTBEAT)
{
return buffer;
}
}
if (DateTime.Now > start.AddMilliseconds(2200)) // was 1200 , now 2.2 sec
return new byte[0];
}
}
public void sendPacket(object indata)
{
bool validPacket = false;
byte a = 0;
foreach (Type ty in MAVLINK_MESSAGE_INFO)
{
if (ty == indata.GetType())
{
validPacket = true;
generatePacket(a, indata);
return;
}
a++;
}
if (!validPacket)
{
log.Info("Mavlink : NOT VALID PACKET sendPacket() " + indata.GetType().ToString());
}
}
///
/// Generate a Mavlink Packet and write to serial
///
/// type number
/// struct of data
void generatePacket(byte messageType, object indata)
{
lock (objlock)
{
byte[] data;
if (mavlinkversion == 3)
{
data = MavlinkUtil.StructureToByteArray(indata);
}
else
{
data = MavlinkUtil.StructureToByteArrayBigEndian(indata);
}
//Console.WriteLine(DateTime.Now + " PC Doing req "+ messageType + " " + this.BytesToRead);
byte[] packet = new byte[data.Length + 6 + 2];
if (mavlinkversion == 3)
{
packet[0] = 254;
}
else if (mavlinkversion == 2)
{
packet[0] = (byte)'U';
}
packet[1] = (byte)data.Length;
packet[2] = packetcount;
packetcount++;
packet[3] = 255; // this is always 255 - MYGCS
#if MAVLINK10
packet[4] = (byte)MAV_COMPONENT.MAV_COMP_ID_MISSIONPLANNER;
#else
packet[4] = (byte)MAV_COMPONENT.MAV_COMP_ID_WAYPOINTPLANNER;
#endif
packet[5] = messageType;
int i = 6;
foreach (byte b in data)
{
packet[i] = b;
i++;
}
ushort checksum = MavlinkCRC.crc_calculate(packet, packet[1] + 6);
if (mavlinkversion == 3)
{
checksum = MavlinkCRC.crc_accumulate(MAVLINK_MESSAGE_CRCS[messageType], checksum);
}
byte ck_a = (byte)(checksum & 0xFF); ///< High byte
byte ck_b = (byte)(checksum >> 8); ///< Low byte
packet[i] = ck_a;
i += 1;
packet[i] = ck_b;
i += 1;
if (BaseStream.IsOpen)
{
BaseStream.Write(packet, 0, i);
_bytesSentSubj.OnNext(i);
}
try
{
if (logfile != null && logfile.BaseStream.CanWrite)
{
lock (logfile)
{
byte[] datearray = BitConverter.GetBytes((UInt64)((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds * 1000));
Array.Reverse(datearray);
logfile.Write(datearray, 0, datearray.Length);
logfile.Write(packet, 0, i);
}
}
}
catch { }
/*
if (messageType == ArdupilotMega.MAVLink.MAVLINK_MSG_ID_REQUEST_DATA_STREAM)
{
try
{
BinaryWriter bw = new BinaryWriter(File.OpenWrite("serialsent.raw"));
bw.Seek(0, SeekOrigin.End);
bw.Write(packet, 0, i);
bw.Write((byte)'\n');
bw.Close();
}
catch { } // been getting errors from this. people must have it open twice.
}*/
}
}
public bool Write(string line)
{
lock (objlock)
{
BaseStream.Write(line);
}
_bytesSentSubj.OnNext(line.Length);
return true;
}
///
/// Set parameter on apm
///
/// name as a string
///
public bool setParam(string paramname, float value)
{
if (!param.ContainsKey(paramname))
{
log.Warn("Trying to set Param that doesnt exist " + paramname);
return false;
}
if ((float)param[paramname] == value)
{
log.Debug("setParam " + paramname + " not modified");
return true;
}
MainV2.giveComport = true;
var req = new mavlink_param_set_t { target_system = sysid, target_component = compid };
byte[] temp = Encoding.ASCII.GetBytes(paramname);
#if MAVLINK10
Array.Resize(ref temp, 16);
#else
Array.Resize(ref temp, 15);
#endif
req.param_id = temp;
req.param_value = (value);
generatePacket(MAVLINK_MSG_ID_PARAM_SET, req);
log.InfoFormat("setParam '{0}' = '{1}' sysid {2} compid {3}", paramname, req.param_value, sysid, compid);
DateTime start = DateTime.Now;
int retrys = 3;
while (true)
{
if (!(start.AddMilliseconds(500) > DateTime.Now))
{
if (retrys > 0)
{
log.Info("setParam Retry " + retrys);
generatePacket(MAVLINK_MSG_ID_PARAM_SET, req);
start = DateTime.Now;
retrys--;
continue;
}
MainV2.giveComport = false;
throw new Exception("Timeout on read - setParam " + paramname);
}
byte[] buffer = readPacket();
if (buffer.Length > 5)
{
if (buffer[5] == MAVLINK_MSG_ID_PARAM_VALUE)
{
mavlink_param_value_t par = buffer.ByteArrayToStructure(6);
string st = System.Text.ASCIIEncoding.ASCII.GetString(par.param_id);
int pos = st.IndexOf('\0');
if (pos != -1)
{
st = st.Substring(0, pos);
}
if (st != paramname)
{
log.InfoFormat("MAVLINK bad param responce - {0} vs {1}", paramname, st);
continue;
}
param[st] = (par.param_value);
MainV2.giveComport = false;
//System.Threading.Thread.Sleep(100);//(int)(8.5 * 5)); // 8.5ms per byte
return true;
}
}
}
}
/*
public Bitmap getImage()
{
MemoryStream ms = new MemoryStream();
}
*/
public void getParamList()
{
frmProgressReporter = new ProgressReporterDialogue
{
StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen,
Text = "Getting Params"
};
frmProgressReporter.DoWork += FrmProgressReporterGetParams;
frmProgressReporter.UpdateProgressAndStatus(-1, "Getting Params...");
ThemeManager.ApplyThemeTo(frmProgressReporter);
frmProgressReporter.RunBackgroundOperationAsync();
if (ParamListChanged != null)
{
ParamListChanged(this, null);
}
}
void FrmProgressReporterGetParams(object sender, ProgressWorkerEventArgs e)
{
Hashtable old = new Hashtable(param);
getParamListBG();
if (frmProgressReporter.doWorkArgs.CancelRequested)
{
param = old;
}
}
///
/// Get param list from apm
///
///
private Hashtable getParamListBG()
{
MainV2.giveComport = true;
List got = new List();
// clear old
param = new Hashtable();
int retrys = 6;
int param_count = 0;
int param_total = 1;
goagain:
mavlink_param_request_list_t req = new mavlink_param_request_list_t();
req.target_system = sysid;
req.target_component = compid;
generatePacket(MAVLINK_MSG_ID_PARAM_REQUEST_LIST, req);
DateTime start = DateTime.Now;
DateTime restart = DateTime.Now;
DateTime lastmessage = DateTime.MinValue;
//hires.Stopwatch stopwatch = new hires.Stopwatch();
int packets = 0;
do
{
if (frmProgressReporter.doWorkArgs.CancelRequested)
{
frmProgressReporter.doWorkArgs.CancelAcknowledged = true;
MainV2.giveComport = false;
frmProgressReporter.doWorkArgs.ErrorMessage = "User Canceled";
return param;
}
// 4 seconds between valid packets
if (!(start.AddMilliseconds(4000) > DateTime.Now))
{
if (retrys > 0)
{
log.InfoFormat("getParamList Retry {0} sys {1} comp {2}", retrys, sysid, compid);
generatePacket(MAVLINK_MSG_ID_PARAM_REQUEST_LIST, req);
start = DateTime.Now;
retrys--;
continue;
}
MainV2.giveComport = false;
if (packets > 0 && param_total == 1)
{
throw new Exception("Timeout on read - getParamList\n" + packets + " Packets where received, but no paramater packets where received\n");
}
if (packets == 0)
{
throw new Exception("Timeout on read - getParamList\nNo Packets where received\n");
}
throw new Exception("Timeout on read - getParamList\nReceived: " + got.Count + " of " + param_total + " after 6 retrys\n\nPlease Check\n1. Link Speed\n2. Link Quality\n3. Hardware hasn't hung");
}
//Console.WriteLine(DateTime.Now.Millisecond + " gp0 ");
byte[] buffer = readPacket();
//Console.WriteLine(DateTime.Now.Millisecond + " gp1 ");
if (buffer.Length > 5)
{
packets++;
// stopwatch.Start();
if (buffer[5] == MAVLINK_MSG_ID_PARAM_VALUE)
{
restart = DateTime.Now;
start = DateTime.Now;
mavlink_param_value_t par = buffer.ByteArrayToStructure(6);
// set new target
param_total = (par.param_count);
string paramID = System.Text.ASCIIEncoding.ASCII.GetString(par.param_id);
int pos = paramID.IndexOf('\0');
if (pos != -1)
{
paramID = paramID.Substring(0, pos);
}
// check if we already have it
if (got.Contains(par.param_index))
{
log.Info("Already got " + (par.param_index) + " '" + paramID + "'");
this.frmProgressReporter.UpdateProgressAndStatus((got.Count * 100) / param_total, "Already Got param " + paramID);
continue;
}
//Console.WriteLine(DateTime.Now.Millisecond + " gp2 ");
if (!MainV2.MONO)
log.Info(DateTime.Now.Millisecond + " got param " + (par.param_index) + " of " + (par.param_count) + " name: " + paramID);
//Console.WriteLine(DateTime.Now.Millisecond + " gp2a ");
param[paramID] = (par.param_value);
//Console.WriteLine(DateTime.Now.Millisecond + " gp2b ");
param_count++;
got.Add(par.param_index);
//Console.WriteLine(DateTime.Now.Millisecond + " gp3 ");
this.frmProgressReporter.UpdateProgressAndStatus((got.Count * 100) / param_total, "Got param " + paramID);
// we have them all - lets escape eq total = 176 index = 0-175
if (par.param_index == (param_total - 1))
break;
}
else
{
//Console.WriteLine(DateTime.Now + " PC paramlist " + buffer[5] + " want " + MAVLINK_MSG_ID_PARAM_VALUE + " btr " + BaseStream.BytesToRead);
}
//stopwatch.Stop();
// Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
// Console.WriteLine(DateTime.Now.Millisecond + " gp4 " + BaseStream.BytesToRead);
}
} while (got.Count < param_total);
if (got.Count != param_total)
{
if (retrys > 0)
{
this.frmProgressReporter.UpdateProgressAndStatus((got.Count * 100) / param_total, "Getting missed params");
retrys--;
goto goagain;
}
throw new Exception("Missing Params");
}
MainV2.giveComport = false;
return param;
}
public float GetParam(string name)
{
return GetParam(name);
}
public float GetParam(int index)
{
return GetParam("", index);
}
///
/// Get param by either index or name
///
///
///
///
internal float GetParam(string name = "", int index = -1)
{
if (name == "" && index == -1)
return 0;
MainV2.giveComport = true;
byte[] buffer;
mavlink_param_request_list_t req = new mavlink_param_request_list_t();
req.target_system = sysid;
req.target_component = compid;
generatePacket(MAVLINK_MSG_ID_PARAM_REQUEST_READ, req);
DateTime start = DateTime.Now;
int retrys = 3;
while (true)
{
if (!(start.AddMilliseconds(200) > DateTime.Now))
{
if (retrys > 0)
{
log.Info("GetParam Retry " + retrys);
generatePacket(MAVLINK_MSG_ID_PARAM_REQUEST_READ, req);
start = DateTime.Now;
retrys--;
continue;
}
MainV2.giveComport = false;
throw new Exception("Timeout on read - GetParam");
}
buffer = readPacket();
if (buffer.Length > 5)
{
if (buffer[5] == MAVLINK_MSG_ID_PARAM_VALUE)
{
MainV2.giveComport = false;
mavlink_param_value_t par = buffer.ByteArrayToStructure(6);
return par.param_value;
}
}
}
}
public static void modifyParamForDisplay(bool fromapm, string paramname, ref float value)
{
if (paramname.ToUpper().EndsWith("_IMAX") || paramname.ToUpper().EndsWith("ALT_HOLD_RTL") || paramname.ToUpper().EndsWith("APPROACH_ALT") || paramname.ToUpper().EndsWith("TRIM_ARSPD_CM") || paramname.ToUpper().EndsWith("MIN_GNDSPD_CM")
|| paramname.ToUpper().EndsWith("XTRK_ANGLE_CD") || paramname.ToUpper().EndsWith("LIM_PITCH_MAX") || paramname.ToUpper().EndsWith("LIM_PITCH_MIN")
|| paramname.ToUpper().EndsWith("LIM_ROLL_CD") || paramname.ToUpper().EndsWith("PITCH_MAX") || paramname.ToUpper().EndsWith("WP_SPEED_MAX"))
{
if (paramname.ToUpper().EndsWith("THR_RATE_IMAX") || paramname.ToUpper().EndsWith("THR_HOLD_IMAX"))
return;
if (fromapm)
{
value /= 100.0f;
}
else
{
value *= 100.0f;
}
}
else if (paramname.ToUpper().StartsWith("TUNE_"))
{
if (fromapm)
{
value /= 1000.0f;
}
else
{
value *= 1000.0f;
}
}
}
///
/// Stops all requested data packets.
///
public void stopall(bool forget)
{
mavlink_request_data_stream_t req = new mavlink_request_data_stream_t();
req.target_system = sysid;
req.target_component = compid;
req.req_message_rate = 10;
req.start_stop = 0; // stop
req.req_stream_id = 0; // all
// no error on bad
try
{
generatePacket(MAVLINK_MSG_ID_REQUEST_DATA_STREAM, req);
System.Threading.Thread.Sleep(20);
generatePacket(MAVLINK_MSG_ID_REQUEST_DATA_STREAM, req);
System.Threading.Thread.Sleep(20);
generatePacket(MAVLINK_MSG_ID_REQUEST_DATA_STREAM, req);
log.Info("Stopall Done");
}
catch { }
}
public void setWPACK()
{
MAVLink.mavlink_mission_ack_t req = new MAVLink.mavlink_mission_ack_t();
req.target_system = sysid;
req.target_component = compid;
req.type = 0;
generatePacket(MAVLINK_MSG_ID_MISSION_ACK, req);
}
public bool setWPCurrent(ushort index)
{
#if MAVLINK10
MainV2.giveComport = true;
byte[] buffer;
mavlink_mission_set_current_t req = new mavlink_mission_set_current_t();
req.target_system = sysid;
req.target_component = compid;
req.seq = index;
generatePacket(MAVLINK_MSG_ID_MISSION_SET_CURRENT, req);
DateTime start = DateTime.Now;
int retrys = 5;
while (true)
{
if (!(start.AddMilliseconds(2000) > DateTime.Now))
{
if (retrys > 0)
{
log.Info("setWPCurrent Retry " + retrys);
generatePacket(MAVLINK_MSG_ID_MISSION_SET_CURRENT, req);
start = DateTime.Now;
retrys--;
continue;
}
MainV2.giveComport = false;
throw new Exception("Timeout on read - setWPCurrent");
}
buffer = readPacket();
if (buffer.Length > 5)
{
if (buffer[5] == MAVLINK_MSG_ID_MISSION_CURRENT)
{
MainV2.giveComport = false;
return true;
}
}
}
}
[Obsolete("Mavlink 09", true)]
public bool doAction(object actionid)
{
// mavlink 09
throw new NotImplementedException();
}
public bool doARM(bool armit)
{
return doCommand(MAV_CMD.COMPONENT_ARM_DISARM, armit ? 0 : 1, 0, 0, 0, 0, 0, 0);
}
public bool doCommand(MAV_CMD actionid, float p1, float p2, float p3, float p4, float p5, float p6, float p7)
{
MainV2.giveComport = true;
byte[] buffer;
mavlink_command_long_t req = new mavlink_command_long_t();
req.target_system = sysid;
req.target_component = compid;
if (actionid == MAV_CMD.COMPONENT_ARM_DISARM)
{
req.target_component = (byte)MAV_COMPONENT.MAV_COMP_ID_SYSTEM_CONTROL;
}
req.command = (ushort)actionid;
req.param1 = p1;
req.param2 = p2;
req.param3 = p3;
req.param4 = p4;
req.param5 = p5;
req.param6 = p6;
req.param7 = p7;
generatePacket(MAVLINK_MSG_ID_COMMAND_LONG, req);
DateTime start = DateTime.Now;
int retrys = 3;
int timeout = 2000;
// imu calib take a little while
if (actionid == MAV_CMD.PREFLIGHT_CALIBRATION)
{
retrys = 1;
timeout = 25000;
} else if (actionid == MAV_CMD.PREFLIGHT_REBOOT_SHUTDOWN) {
generatePacket(MAVLINK_MSG_ID_COMMAND_LONG, req);
return true;
}
while (true)
{
if (!(start.AddMilliseconds(timeout) > DateTime.Now))
{
if (retrys > 0)
{
log.Info("doAction Retry " + retrys);
generatePacket(MAVLINK_MSG_ID_COMMAND_LONG, req);
start = DateTime.Now;
retrys--;
continue;
}
MainV2.giveComport = false;
throw new Exception("Timeout on read - doAction");
}
buffer = readPacket();
if (buffer.Length > 5)
{
if (buffer[5] == MAVLINK_MSG_ID_COMMAND_ACK)
{
var ack = buffer.ByteArrayToStructure(6);
if (ack.result == (byte)MAV_RESULT.ACCEPTED)
{
MainV2.giveComport = false;
return true;
}
else
{
MainV2.giveComport = false;
return false;
}
}
}
}
#else
MainV2.giveComport = true;
byte[] buffer;
mavlink_waypoint_set_current_t req = new mavlink_waypoint_set_current_t();
req.target_system = sysid;
req.target_component = compid;
req.seq = index;
generatePacket(MAVLINK_MSG_ID_WAYPOINT_SET_CURRENT, req);
DateTime start = DateTime.Now;
int retrys = 5;
while (true)
{
if (!(start.AddMilliseconds(2000) > DateTime.Now))
{
if (retrys > 0)
{
log.Info("setWPCurrent Retry " + retrys);
generatePacket(MAVLINK_MSG_ID_WAYPOINT_SET_CURRENT, req);
start = DateTime.Now;
retrys--;
continue;
}
MainV2.giveComport = false;
throw new Exception("Timeout on read - setWPCurrent");
}
buffer = readPacket();
if (buffer.Length > 5)
{
if (buffer[5] == MAVLINK_MSG_ID_WAYPOINT_CURRENT)
{
MainV2.giveComport = false;
return true;
}
}
}
}
public bool doCommand(ArdupilotMega.MAVLink.MAV_CMD actionid, float p1, float p2, float p3, float p4, float p5, float p6, float p7)
{
// mavlink 10
throw new NotImplementedException();
}
public bool doAction(object actionidin)
{
MAV_ACTION actionid = (MAV_ACTION)actionidin;
MainV2.giveComport = true;
byte[] buffer;
mavlink_action_t req = new mavlink_action_t();
req.target = sysid;
req.target_component = compid;
req.action = (byte)actionid;
generatePacket(MAVLINK_MSG_ID_ACTION, req);
DateTime start = DateTime.Now;
int retrys = 3;
int timeout = 2000;
// imu calib take a little while
if (actionid == MAV_ACTION.MAV_ACTION_CALIBRATE_ACC ||
actionid == MAV_ACTION.MAV_ACTION_CALIBRATE_GYRO ||
actionid == MAV_ACTION.MAV_ACTION_CALIBRATE_MAG ||
actionid == MAV_ACTION.MAV_ACTION_CALIBRATE_PRESSURE ||
actionid == MAV_ACTION.MAV_ACTION_REBOOT)
{
retrys = 1;
timeout = 20000;
}
while (true)
{
if (!(start.AddMilliseconds(timeout) > DateTime.Now))
{
if (retrys > 0)
{
log.Info("doAction Retry " + retrys);
generatePacket(MAVLINK_MSG_ID_ACTION, req);
start = DateTime.Now;
retrys--;
continue;
}
MainV2.giveComport = false;
throw new Exception("Timeout on read - doAction");
}
buffer = readPacket();
if (buffer.Length > 5)
{
if (buffer[5] == MAVLINK_MSG_ID_ACTION_ACK)
{
if (buffer[7] == 1)
{
MainV2.giveComport = false;
return true;
}
else
{
MainV2.giveComport = false;
return false;
}
}
}
}
#endif
}
public void requestDatastream(byte id, byte hzrate)
{
double pps = 0;
switch (id)
{
case (byte)MAVLink.MAV_DATA_STREAM.ALL:
break;
case (byte)MAVLink.MAV_DATA_STREAM.EXTENDED_STATUS:
if (packetspersecondbuild[MAVLINK_MSG_ID_SYS_STATUS] < DateTime.Now.AddSeconds(-2))
break;
pps = packetspersecond[MAVLINK_MSG_ID_SYS_STATUS];
if (hzratecheck(pps, hzrate))
{
return;
}
break;
case (byte)MAVLink.MAV_DATA_STREAM.EXTRA1:
if (packetspersecondbuild[MAVLINK_MSG_ID_ATTITUDE] < DateTime.Now.AddSeconds(-2))
break;
pps = packetspersecond[MAVLINK_MSG_ID_ATTITUDE];
if (hzratecheck(pps, hzrate))
{
return;
}
break;
case (byte)MAVLink.MAV_DATA_STREAM.EXTRA2:
if (packetspersecondbuild[MAVLINK_MSG_ID_VFR_HUD] < DateTime.Now.AddSeconds(-2))
break;
pps = packetspersecond[MAVLINK_MSG_ID_VFR_HUD];
if (hzratecheck(pps, hzrate))
{
return;
}
break;
case (byte)MAVLink.MAV_DATA_STREAM.EXTRA3:
if (packetspersecondbuild[MAVLINK_MSG_ID_AHRS] < DateTime.Now.AddSeconds(-2))
break;
pps = packetspersecond[MAVLINK_MSG_ID_AHRS];
if (hzratecheck(pps, hzrate))
{
return;
}
break;
case (byte)MAVLink.MAV_DATA_STREAM.POSITION:
if (packetspersecondbuild[MAVLINK_MSG_ID_GLOBAL_POSITION_INT] < DateTime.Now.AddSeconds(-2))
break;
pps = packetspersecond[MAVLINK_MSG_ID_GLOBAL_POSITION_INT];
if (hzratecheck(pps, hzrate))
{
return;
}
break;
case (byte)MAVLink.MAV_DATA_STREAM.RAW_CONTROLLER:
if (packetspersecondbuild[MAVLINK_MSG_ID_RC_CHANNELS_SCALED] < DateTime.Now.AddSeconds(-2))
break;
pps = packetspersecond[MAVLINK_MSG_ID_RC_CHANNELS_SCALED];
if (hzratecheck(pps, hzrate))
{
return;
}
break;
case (byte)MAVLink.MAV_DATA_STREAM.RAW_SENSORS:
if (packetspersecondbuild[MAVLINK_MSG_ID_RAW_IMU] < DateTime.Now.AddSeconds(-2))
break;
pps = packetspersecond[MAVLINK_MSG_ID_RAW_IMU];
if (hzratecheck(pps, hzrate))
{
return;
}
break;
case (byte)MAVLink.MAV_DATA_STREAM.RC_CHANNELS:
if (packetspersecondbuild[MAVLINK_MSG_ID_RC_CHANNELS_RAW] < DateTime.Now.AddSeconds(-2))
break;
pps = packetspersecond[MAVLINK_MSG_ID_RC_CHANNELS_RAW];
if (hzratecheck(pps, hzrate))
{
return;
}
break;
}
//packetspersecond[temp[5]];
if (pps == 0 && hzrate == 0)
{
return;
}
log.InfoFormat("Request stream {0} at {1} hz", Enum.Parse(typeof(MAV_DATA_STREAM), id.ToString()), hzrate);
getDatastream(id, hzrate);
}
// returns true for ok
bool hzratecheck(double pps, int hzrate)
{
if (hzrate == 0 && pps == 0)
{
return true;
}
else if (hzrate == 1 && pps >= 0.5 && pps <= 2)
{
return true;
}
else if (hzrate == 3 && pps >= 2 && hzrate < 5)
{
return true;
}
else if (hzrate == 10 && pps > 5 && hzrate < 15)
{
return true;
}
else if (hzrate > 15 && pps > 15)
{
return true;
}
return false;
}
void getDatastream(byte id, byte hzrate)
{
mavlink_request_data_stream_t req = new mavlink_request_data_stream_t();
req.target_system = sysid;
req.target_component = compid;
req.req_message_rate = hzrate;
req.start_stop = 1; // start
req.req_stream_id = id; // id
// send each one twice.
generatePacket(MAVLINK_MSG_ID_REQUEST_DATA_STREAM, req);
generatePacket(MAVLINK_MSG_ID_REQUEST_DATA_STREAM, req);
}
///
/// Returns WP count
///
///
public byte getWPCount()
{
MainV2.giveComport = true;
byte[] buffer;
#if MAVLINK10
mavlink_mission_request_list_t req = new mavlink_mission_request_list_t();
req.target_system = sysid;
req.target_component = compid;
// request list
generatePacket(MAVLINK_MSG_ID_MISSION_REQUEST_LIST, req);
DateTime start = DateTime.Now;
int retrys = 6;
while (true)
{
if (!(start.AddMilliseconds(500) > DateTime.Now))
{
if (retrys > 0)
{
log.Info("getWPCount Retry " + retrys + " - giv com " + MainV2.giveComport);
generatePacket(MAVLINK_MSG_ID_MISSION_REQUEST_LIST, req);
start = DateTime.Now;
retrys--;
continue;
}
MainV2.giveComport = false;
//return (byte)int.Parse(param["WP_TOTAL"].ToString());
throw new Exception("Timeout on read - getWPCount");
}
buffer = readPacket();
if (buffer.Length > 5)
{
if (buffer[5] == MAVLINK_MSG_ID_MISSION_COUNT)
{
var count = buffer.ByteArrayToStructure(6);
log.Info("wpcount: " + count.count);
MainV2.giveComport = false;
return (byte)count.count; // should be ushort, but apm has limited wp count < byte
}
else
{
log.Info(DateTime.Now + " PC wpcount " + buffer[5] + " need " + MAVLINK_MSG_ID_MISSION_COUNT);
}
}
}
#else
mavlink_waypoint_request_list_t req = new mavlink_waypoint_request_list_t();
req.target_system = sysid;
req.target_component = compid;
// request list
generatePacket(MAVLINK_MSG_ID_WAYPOINT_REQUEST_LIST, req);
DateTime start = DateTime.Now;
int retrys = 6;
while (true)
{
if (!(start.AddMilliseconds(500) > DateTime.Now))
{
if (retrys > 0)
{
log.Info("getWPCount Retry " + retrys + " - giv com " + MainV2.giveComport);
generatePacket(MAVLINK_MSG_ID_WAYPOINT_REQUEST_LIST, req);
start = DateTime.Now;
retrys--;
continue;
}
MainV2.giveComport = false;
//return (byte)int.Parse(param["WP_TOTAL"].ToString());
throw new Exception("Timeout on read - getWPCount");
}
buffer = readPacket();
if (buffer.Length > 5)
{
if (buffer[5] == MAVLINK_MSG_ID_WAYPOINT_COUNT)
{
log.Info("wpcount: " + buffer[9]);
MainV2.giveComport = false;
return buffer[9]; // should be ushort, but apm has limited wp count < byte
}
else
{
log.Info(DateTime.Now + " PC wpcount " + buffer[5] + " need " + MAVLINK_MSG_ID_WAYPOINT_COUNT + " " + this.BaseStream.BytesToRead);
}
}
}
#endif
}
///
/// Gets specfied WP
///
///
/// WP
public Locationwp getWP(ushort index)
{
MainV2.giveComport = true;
Locationwp loc = new Locationwp();
#if MAVLINK10
mavlink_mission_request_t req = new mavlink_mission_request_t();
req.target_system = sysid;
req.target_component = compid;
req.seq = index;
//Console.WriteLine("getwp req "+ DateTime.Now.Millisecond);
// request
generatePacket(MAVLINK_MSG_ID_MISSION_REQUEST, req);
DateTime start = DateTime.Now;
int retrys = 5;
while (true)
{
if (!(start.AddMilliseconds(800) > DateTime.Now)) // apm times out after 1000ms
{
if (retrys > 0)
{
log.Info("getWP Retry " + retrys);
generatePacket(MAVLINK_MSG_ID_MISSION_REQUEST, req);
start = DateTime.Now;
retrys--;
continue;
}
MainV2.giveComport = false;
throw new Exception("Timeout on read - getWP");
}
//Console.WriteLine("getwp read " + DateTime.Now.Millisecond);
byte[] buffer = readPacket();
//Console.WriteLine("getwp readend " + DateTime.Now.Millisecond);
if (buffer.Length > 5)
{
if (buffer[5] == MAVLINK_MSG_ID_MISSION_ITEM)
{
//Console.WriteLine("getwp ans " + DateTime.Now.Millisecond);
//Array.Copy(buffer, 6, buffer, 0, buffer.Length - 6);
var wp = buffer.ByteArrayToStructure(6);
#else
mavlink_waypoint_request_t req = new mavlink_waypoint_request_t();
req.target_system = sysid;
req.target_component = compid;
req.seq = index;
//Console.WriteLine("getwp req "+ DateTime.Now.Millisecond);
// request
generatePacket(MAVLINK_MSG_ID_WAYPOINT_REQUEST, req);
DateTime start = DateTime.Now;
int retrys = 5;
while (true)
{
if (!(start.AddMilliseconds(800) > DateTime.Now)) // apm times out after 1000ms
{
if (retrys > 0)
{
log.Info("getWP Retry " + retrys);
generatePacket(MAVLINK_MSG_ID_WAYPOINT_REQUEST, req);
start = DateTime.Now;
retrys--;
continue;
}
MainV2.giveComport = false;
throw new Exception("Timeout on read - getWP");
}
//Console.WriteLine("getwp read " + DateTime.Now.Millisecond);
byte[] buffer = readPacket();
//Console.WriteLine("getwp readend " + DateTime.Now.Millisecond);
if (buffer.Length > 5)
{
if (buffer[5] == MAVLINK_MSG_ID_WAYPOINT)
{
//Console.WriteLine("getwp ans " + DateTime.Now.Millisecond);
mavlink_waypoint_t wp = buffer.ByteArrayToStructure(6);
#endif
loc.options = (byte)(wp.frame & 0x1);
loc.id = (byte)(wp.command);
loc.p1 = (wp.param1);
loc.p2 = (wp.param2);
loc.p3 = (wp.param3);
loc.p4 = (wp.param4);
loc.alt = ((wp.z));
loc.lat = ((wp.x));
loc.lng = ((wp.y));
/*
if (MainV2.cs.firmware == MainV2.Firmwares.ArduPlane)
{
switch (loc.id)
{ // Switch to map APM command fields inot MAVLink command fields
case (byte)MAV_CMD.LOITER_TURNS:
case (byte)MAV_CMD.TAKEOFF:
case (byte)MAV_CMD.DO_SET_HOME:
//case (byte)MAV_CMD.DO_SET_ROI:
loc.alt = (float)((wp.z));
loc.lat = (float)((wp.x));
loc.lng = (float)((wp.y));
loc.p1 = (float)wp.param1;
break;
case (byte)MAV_CMD.CONDITION_CHANGE_ALT:
loc.lat = (int)wp.param1;
loc.p1 = 0;
break;
case (byte)MAV_CMD.LOITER_TIME:
if (MainV2.APMFirmware == MainV2.Firmwares.ArduPlane)
{
loc.p1 = (byte)(wp.param1 / 10); // APM loiter time is in ten second increments
}
else
{
loc.p1 = (byte)wp.param1;
}
break;
case (byte)MAV_CMD.CONDITION_DELAY:
case (byte)MAV_CMD.CONDITION_DISTANCE:
loc.lat = (int)wp.param1;
break;
case (byte)MAV_CMD.DO_JUMP:
loc.lat = (int)wp.param2;
loc.p1 = (byte)wp.param1;
break;
case (byte)MAV_CMD.DO_REPEAT_SERVO:
loc.lng = (int)wp.param4;
goto case (byte)MAV_CMD.DO_CHANGE_SPEED;
case (byte)MAV_CMD.DO_REPEAT_RELAY:
case (byte)MAV_CMD.DO_CHANGE_SPEED:
loc.lat = (int)wp.param3;
loc.alt = (int)wp.param2;
loc.p1 = (byte)wp.param1;
break;
case (byte)MAV_CMD.DO_SET_PARAMETER:
case (byte)MAV_CMD.DO_SET_RELAY:
case (byte)MAV_CMD.DO_SET_SERVO:
loc.alt = (int)wp.param2;
loc.p1 = (byte)wp.param1;
break;
case (byte)MAV_CMD.WAYPOINT:
loc.p1 = (byte)wp.param1;
break;
}
}
*/
log.InfoFormat("getWP {0} {1} {2} {3} {4} opt {5}", loc.id, loc.p1, loc.alt, loc.lat, loc.lng, loc.options);
break;
}
else
{
log.Info(DateTime.Now + " PC getwp " + buffer[5]);
}
}
}
MainV2.giveComport = false;
return loc;
}
public object DebugPacket(byte[] datin)
{
string text = "";
return DebugPacket(datin, ref text, true);
}
public object DebugPacket(byte[] datin, bool PrintToConsole)
{
string text = "";
return DebugPacket(datin, ref text, PrintToConsole);
}
public object DebugPacket(byte[] datin, ref string text)
{
return DebugPacket(datin, ref text, true);
}
///
/// Print entire decoded packet to console
///
/// packet byte array
/// struct of data
public object DebugPacket(byte[] datin, ref string text, bool PrintToConsole, string delimeter = " ")
{
string textoutput;
try
{
if (datin.Length > 5)
{
byte header = datin[0];
byte length = datin[1];
byte seq = datin[2];
byte sysid = datin[3];
byte compid = datin[4];
byte messid = datin[5];
textoutput = string.Format("{0,2:X}{6}{1,2:X}{6}{2,2:X}{6}{3,2:X}{6}{4,2:X}{6}{5,2:X}{6}", header, length, seq, sysid, compid, messid, delimeter);
object data = Activator.CreateInstance(MAVLINK_MESSAGE_INFO[messid]);
MavlinkUtil.ByteArrayToStructure(datin, ref data, 6);
Type test = data.GetType();
if (PrintToConsole)
{
textoutput = textoutput + test.Name + delimeter;
foreach (var field in test.GetFields())
{
// field.Name has the field's name.
object fieldValue = field.GetValue(data); // Get value
if (field.FieldType.IsArray)
{
textoutput = textoutput + field.Name + delimeter;
byte[] crap = (byte[])fieldValue;
foreach (byte fiel in crap)
{
if (fiel == 0)
{
break;
}
else
{
textoutput = textoutput + (char)fiel;
}
}
textoutput = textoutput + delimeter;
}
else
{
textoutput = textoutput + field.Name + delimeter + fieldValue.ToString() + delimeter;
}
}
textoutput = textoutput + delimeter + "Len" + delimeter + datin.Length + "\r\n";
if (PrintToConsole)
Console.Write(textoutput);
if (text != null)
text = textoutput;
}
return data;
}
}
catch { }
return null;
}
///
/// Sets wp total count
///
///
public void setWPTotal(ushort wp_total)
{
#if MAVLINK10
MainV2.giveComport = true;
mavlink_mission_count_t req = new mavlink_mission_count_t();
req.target_system = sysid;
req.target_component = compid; // MAVLINK_MSG_ID_MISSION_COUNT
req.count = wp_total;
generatePacket(MAVLINK_MSG_ID_MISSION_COUNT, req);
DateTime start = DateTime.Now;
int retrys = 3;
while (true)
{
if (!(start.AddMilliseconds(700) > DateTime.Now))
{
if (retrys > 0)
{
log.Info("setWPTotal Retry " + retrys);
generatePacket(MAVLINK_MSG_ID_MISSION_COUNT, req);
start = DateTime.Now;
retrys--;
continue;
}
MainV2.giveComport = false;
throw new Exception("Timeout on read - setWPTotal");
}
byte[] buffer = readPacket();
if (buffer.Length > 9)
{
if (buffer[5] == MAVLINK_MSG_ID_MISSION_REQUEST)
{
var request = buffer.ByteArrayToStructure(6);
if (request.seq == 0)
{
if (param["WP_TOTAL"] != null)
param["WP_TOTAL"] = (float)wp_total - 1;
if (param["CMD_TOTAL"] != null)
param["CMD_TOTAL"] = (float)wp_total - 1;
wps.Clear();
MainV2.giveComport = false;
return;
}
}
else
{
//Console.WriteLine(DateTime.Now + " PC getwp " + buffer[5]);
}
}
}
#else
MainV2.giveComport = true;
mavlink_waypoint_count_t req = new mavlink_waypoint_count_t();
req.target_system = sysid;
req.target_component = compid; // MAVLINK_MSG_ID_WAYPOINT_COUNT
req.count = wp_total;
generatePacket(MAVLINK_MSG_ID_WAYPOINT_COUNT, req);
DateTime start = DateTime.Now;
int retrys = 3;
while (true)
{
if (!(start.AddMilliseconds(700) > DateTime.Now))
{
if (retrys > 0)
{
log.Info("setWPTotal Retry " + retrys);
generatePacket(MAVLINK_MSG_ID_WAYPOINT_COUNT, req);
start = DateTime.Now;
retrys--;
continue;
}
MainV2.giveComport = false;
throw new Exception("Timeout on read - setWPTotal");
}
byte[] buffer = readPacket();
if (buffer.Length > 9)
{
if (buffer[5] == MAVLINK_MSG_ID_WAYPOINT_REQUEST)
{
mavlink_waypoint_request_t request = buffer.ByteArrayToStructure(6);
if (request.seq == 0)
{
if (param["WP_TOTAL"] != null)
param["WP_TOTAL"] = (float)wp_total - 1;
if (param["CMD_TOTAL"] != null)
param["CMD_TOTAL"] = (float)wp_total - 1;
MainV2.giveComport = false;
return;
}
}
else
{
//Console.WriteLine(DateTime.Now + " PC getwp " + buffer[5]);
}
}
}
#endif
}
///
/// Save wp to eeprom
///
/// location struct
/// wp no
/// global or relative
/// 0 = no , 2 = guided mode
public MAV_MISSION_RESULT setWP(Locationwp loc, ushort index, MAV_FRAME frame, byte current = 0)
{
MainV2.giveComport = true;
mavlink_mission_item_t req = new mavlink_mission_item_t();
req.target_system = sysid;
req.target_component = compid; // MAVLINK_MSG_ID_MISSION_ITEM
req.command = loc.id;
req.param1 = loc.p1;
req.current = current;
req.frame = (byte)frame;
req.y = (float)(loc.lng);
req.x = (float)(loc.lat);
req.z = (float)(loc.alt);
req.param1 = loc.p1;
req.param2 = loc.p2;
req.param3 = loc.p3;
req.param4 = loc.p4;
req.seq = index;
log.InfoFormat("setWP {6} frame {0} cmd {1} p1 {2} x {3} y {4} z {5}", req.frame, req.command, req.param1, req.x, req.y, req.z, index);
// request
generatePacket(MAVLINK_MSG_ID_MISSION_ITEM, req);
DateTime start = DateTime.Now;
int retrys = 10;
while (true)
{
if (!(start.AddMilliseconds(150) > DateTime.Now))
{
if (retrys > 0)
{
log.Info("setWP Retry " + retrys);
generatePacket(MAVLINK_MSG_ID_MISSION_ITEM, req);
start = DateTime.Now;
retrys--;
continue;
}
MainV2.giveComport = false;
throw new Exception("Timeout on read - setWP");
}
byte[] buffer = readPacket();
if (buffer.Length > 5)
{
if (buffer[5] == MAVLINK_MSG_ID_MISSION_ACK)
{
var ans = buffer.ByteArrayToStructure(6);
log.Info("set wp " + index + " ACK 47 : " + buffer[5] + " ans " + Enum.Parse(typeof(MAV_MISSION_RESULT), ans.type.ToString()));
if (req.current == 2)
{
GuidedMode = req;
}
else if (req.current == 3)
{
}
else
{
wps[req.seq] = req;
}
return (MAV_MISSION_RESULT)ans.type;
}
else if (buffer[5] == MAVLINK_MSG_ID_MISSION_REQUEST)
{
var ans = buffer.ByteArrayToStructure(6);
if (ans.seq == (index + 1))
{
log.Info("set wp doing " + index + " req " + ans.seq + " REQ 40 : " + buffer[5]);
MainV2.giveComport = false;
if (req.current == 2)
{
GuidedMode = req;
}
else if (req.current == 3)
{
}
else
{
wps[req.seq] = req;
}
return MAV_MISSION_RESULT.MAV_MISSION_ACCEPTED;
}
else
{
log.InfoFormat("set wp fail doing " + index + " req " + ans.seq + " ACK 47 or REQ 40 : " + buffer[5] + " seq {0} ts {1} tc {2}", req.seq, req.target_system, req.target_component);
//break;
}
}
else
{
//Console.WriteLine(DateTime.Now + " PC setwp " + buffer[5]);
}
}
}
// return MAV_MISSION_RESULT.MAV_MISSION_INVALID;
}
public void setNextWPTargetAlt(ushort wpno, float alt)
{
// get the existing wp
Locationwp current = getWP(wpno);
mavlink_mission_write_partial_list_t req = new mavlink_mission_write_partial_list_t();
req.target_system = sysid;
req.target_component = compid;
req.start_index = (short)wpno;
req.end_index = (short)wpno;
// change the alt
current.alt = alt;
// send a request to update single point
generatePacket(MAVLINK_MSG_ID_MISSION_WRITE_PARTIAL_LIST, req);
Thread.Sleep(10);
generatePacket(MAVLINK_MSG_ID_MISSION_WRITE_PARTIAL_LIST, req);
MAV_FRAME frame = (current.options & 0x1) == 0 ? MAV_FRAME.GLOBAL : MAV_FRAME.GLOBAL_RELATIVE_ALT;
//send the point with new alt
setWP(current, wpno, MAV_FRAME.GLOBAL_RELATIVE_ALT, 0);
// set the point as current to reload the modified command
setWPCurrent(wpno);
}
public void setGuidedModeWP(Locationwp gotohere)
{
if (gotohere.alt == 0 || gotohere.lat == 0 || gotohere.lng == 0)
return;
MainV2.giveComport = true;
try
{
gotohere.id = (byte)MAV_CMD.WAYPOINT;
MAV_MISSION_RESULT ans = MainV2.comPort.setWP(gotohere, 0, MAVLink.MAV_FRAME.GLOBAL_RELATIVE_ALT, (byte)2);
if (ans != MAV_MISSION_RESULT.MAV_MISSION_ACCEPTED)
throw new Exception("Guided Mode Failed");
}
catch (Exception ex) { log.Error(ex); }
MainV2.giveComport = false;
}
public void setNewWPAlt(Locationwp gotohere)
{
MainV2.giveComport = true;
try
{
gotohere.id = (byte)MAV_CMD.WAYPOINT;
MAV_MISSION_RESULT ans = MainV2.comPort.setWP(gotohere, 0, MAVLink.MAV_FRAME.GLOBAL_RELATIVE_ALT, (byte)3);
if (ans != MAV_MISSION_RESULT.MAV_MISSION_ACCEPTED)
throw new Exception("Alt Change Failed");
}
catch (Exception ex) { MainV2.giveComport = false; log.Error(ex); throw; }
MainV2.giveComport = false;
}
public void setDigicamConfigure()
{
// not implmented
}
public void setDigicamControl(bool shot)
{
mavlink_digicam_control_t req = new mavlink_digicam_control_t();
req.target_system = sysid;
req.target_component = compid;
req.shot = (shot == true) ? (byte)1 : (byte)0;
generatePacket(MAVLINK_MSG_ID_DIGICAM_CONTROL, req);
System.Threading.Thread.Sleep(20);
generatePacket(MAVLINK_MSG_ID_DIGICAM_CONTROL, req);
}
public void setMountConfigure(MAV_MOUNT_MODE mountmode, bool stabroll, bool stabpitch, bool stabyaw)
{
mavlink_mount_configure_t req = new mavlink_mount_configure_t();
req.target_system = sysid;
req.target_component = compid;
req.mount_mode = (byte)mountmode;
req.stab_pitch = (stabpitch == true) ? (byte)1 : (byte)0;
req.stab_roll = (stabroll == true) ? (byte)1 : (byte)0;
req.stab_yaw = (stabyaw == true) ? (byte)1 : (byte)0;
generatePacket(MAVLINK_MSG_ID_MOUNT_CONFIGURE, req);
System.Threading.Thread.Sleep(20);
generatePacket(MAVLINK_MSG_ID_MOUNT_CONFIGURE, req);
}
public void setMountControl(double pa, double pb, double pc, bool islatlng)
{
mavlink_mount_control_t req = new mavlink_mount_control_t();
req.target_system = sysid;
req.target_component = compid;
if (!islatlng)
{
req.input_a = (int)pa;
req.input_b = (int)pb;
req.input_c = (int)pc;
}
else
{
req.input_a = (int)(pa * 10000000.0);
req.input_b = (int)(pb * 10000000.0);
req.input_c = (int)(pc * 100.0);
}
generatePacket(MAVLINK_MSG_ID_MOUNT_CONTROL, req);
System.Threading.Thread.Sleep(20);
generatePacket(MAVLINK_MSG_ID_MOUNT_CONTROL, req);
}
public void setMode(string modein)
{
try
{
MAVLink.mavlink_set_mode_t mode = new MAVLink.mavlink_set_mode_t();
if (translateMode(modein, ref mode))
{
setMode(mode);
}
}
catch { System.Windows.Forms.MessageBox.Show("Failed to change Modes"); }
}
public void setMode(mavlink_set_mode_t mode, MAV_MODE_FLAG base_mode = 0)
{
mode.base_mode |= (byte)base_mode;
generatePacket((byte)MAVLink.MAVLINK_MSG_ID_SET_MODE, mode);
System.Threading.Thread.Sleep(10);
generatePacket((byte)MAVLink.MAVLINK_MSG_ID_SET_MODE, mode);
}
///
/// used for last bad serial characters
///
byte[] lastbad = new byte[2];
///
/// Serial Reader to read mavlink packets. POLL method
///
///
public byte[] readPacket()
{
byte[] buffer = new byte[300];
int count = 0;
int length = 0;
int readcount = 0;
lastbad = new byte[2];
byte[] headbuffer = new byte[6];
BaseStream.ReadTimeout = 1200; // 1200 ms between chars - the gps detection requires this.
DateTime start = DateTime.Now;
//Console.WriteLine(DateTime.Now.Millisecond + " SR0 " + BaseStream.BytesToRead);
try
{
// test fabs idea - http://diydrones.com/profiles/blogs/flying-with-joystick?commentId=705844%3AComment%3A818712&xg_source=msg_com_blogpost
if (BaseStream.IsOpen && BaseStream.BytesToWrite > 0)
{
// slow down execution. else 100% cpu
Thread.Sleep(1);
return new byte[0];
}
}
catch (Exception ex) { log.Info(ex.ToString()); }
lock (readlock)
{
//Console.WriteLine(DateTime.Now.Millisecond + " SR1 " + BaseStream.BytesToRead);
while (BaseStream.IsOpen || logreadmode)
{
try
{
if (readcount > 300)
{
log.Info("MAVLink readpacket No valid mavlink packets");
break;
}
readcount++;
if (logreadmode)
{
try
{
if (logplaybackfile.BaseStream.Position == 0)
{
if (logplaybackfile.PeekChar() == '-')
{
oldlogformat = true;
}
else
{
oldlogformat = false;
}
}
}
catch { oldlogformat = false; }
if (oldlogformat)
{
buffer = readlogPacket(); //old style log
}
else
{
buffer = readlogPacketMavlink();
}
}
else
{
MainV2.cs.datetime = DateTime.Now;
DateTime to = DateTime.Now.AddMilliseconds(BaseStream.ReadTimeout);
// Console.WriteLine(DateTime.Now.Millisecond + " SR1a " + BaseStream.BytesToRead);
while (BaseStream.BytesToRead <= 0)
{
if (DateTime.Now > to)
{
log.InfoFormat("MAVLINK: 1 wait time out btr {0} len {1}", BaseStream.BytesToRead, length);
throw new Exception("Timeout");
}
System.Threading.Thread.Sleep(1);
//Console.WriteLine(DateTime.Now.Millisecond + " SR0b " + BaseStream.BytesToRead);
}
//Console.WriteLine(DateTime.Now.Millisecond + " SR1a " + BaseStream.BytesToRead);
if (BaseStream.IsOpen)
{
BaseStream.Read(buffer, count, 1);
if (rawlogfile != null && rawlogfile.BaseStream.CanWrite)
rawlogfile.Write(buffer[count]);
}
//Console.WriteLine(DateTime.Now.Millisecond + " SR1b " + BaseStream.BytesToRead);
}
}
catch (Exception e) { log.Info("MAVLink readpacket read error: " + e.ToString()); break; }
// check if looks like a mavlink packet and check for exclusions and write to console
if (buffer[0] != 254)
{
if (buffer[0] >= 0x20 && buffer[0] <= 127 || buffer[0] == '\n' || buffer[0] == '\r')
{
TCPConsole.Write(buffer[0]);
Console.Write((char)buffer[0]);
}
_bytesReceivedSubj.OnNext(1);
count = 0;
lastbad[0] = lastbad[1];
lastbad[1] = buffer[0];
buffer[1] = 0;
continue;
}
// reset count on valid packet
readcount = 0;
//Console.WriteLine(DateTime.Now.Millisecond + " SR2 " + BaseStream.BytesToRead);
// check for a header
if (buffer[0] == 254)
{
// if we have the header, and no other chars, get the length and packet identifiers
if (count == 0 && !logreadmode)
{
DateTime to = DateTime.Now.AddMilliseconds(BaseStream.ReadTimeout);
while (BaseStream.BytesToRead < 5)
{
if (DateTime.Now > to)
{
log.InfoFormat("MAVLINK: 2 wait time out btr {0} len {1}", BaseStream.BytesToRead, length);
throw new Exception("Timeout");
}
System.Threading.Thread.Sleep(1);
//Console.WriteLine(DateTime.Now.Millisecond + " SR0b " + BaseStream.BytesToRead);
}
int read = BaseStream.Read(buffer, 1, 5);
count = read;
if (rawlogfile != null && rawlogfile.BaseStream.CanWrite)
rawlogfile.Write(buffer, 1, read);
}
// packet length
length = buffer[1] + 6 + 2 - 2; // data + header + checksum - U - length
if (count >= 5 || logreadmode)
{
if (sysid != 0)
{
if (sysid != buffer[3] || compid != buffer[4])
{
if (buffer[3] == '3' && buffer[4] == 'D')
{
// this is a 3dr radio rssi packet
}
else
{
log.InfoFormat("Mavlink Bad Packet (not addressed to this MAV) got {0} {1} vs {2} {3}", buffer[3], buffer[4], sysid, compid);
return new byte[0];
}
}
}
try
{
if (logreadmode)
{
}
else
{
DateTime to = DateTime.Now.AddMilliseconds(BaseStream.ReadTimeout);
while (BaseStream.BytesToRead < (length - 4))
{
if (DateTime.Now > to)
{
log.InfoFormat("MAVLINK: 3 wait time out btr {0} len {1}", BaseStream.BytesToRead, length);
break;
}
System.Threading.Thread.Sleep(1);
}
if (BaseStream.IsOpen)
{
int read = BaseStream.Read(buffer, 6, length - 4);
if (rawlogfile != null && rawlogfile.BaseStream.CanWrite)
{
// write only what we read, temp is the whole packet, so 6-end
rawlogfile.Write(buffer, 6, read);
}
}
}
count = length + 2;
}
catch { break; }
break;
}
}
count++;
if (count == 299)
break;
}
//Console.WriteLine(DateTime.Now.Millisecond + " SR3 " + BaseStream.BytesToRead);
}// end readlock
Array.Resize(ref buffer, count);
_bytesReceivedSubj.OnNext(buffer.Length);
if (packetlosttimer.AddSeconds(5) < DateTime.Now)
{
packetlosttimer = DateTime.Now;
packetslost = (packetslost * 0.8f);
packetsnotlost = (packetsnotlost * 0.8f);
}
MainV2.cs.linkqualitygcs = (ushort)((packetsnotlost / (packetsnotlost + packetslost)) * 100.0);
if (bpstime.Second != DateTime.Now.Second && !logreadmode)
{
Console.Write("bps {0} loss {1} left {2} mem {3} \n", bps1, synclost, BaseStream.BytesToRead, System.GC.GetTotalMemory(false) / 1024 / 1024.0);
bps2 = bps1; // prev sec
bps1 = 0; // current sec
bpstime = DateTime.Now;
}
bps1 += buffer.Length;
bps = (bps1 + bps2) / 2;
if (buffer.Length >= 5 && buffer[3] == 255 && logreadmode) // gcs packet
{
getWPsfromstream(ref buffer);
return buffer;// new byte[0];
}
ushort crc = MavlinkCRC.crc_calculate(buffer, buffer.Length - 2);
if (buffer.Length > 5 && buffer[0] == 254)
{
crc = MavlinkCRC.crc_accumulate(MAVLINK_MESSAGE_CRCS[buffer[5]], crc);
}
if (buffer.Length > 5 && buffer[1] != MAVLINK_MESSAGE_LENGTHS[buffer[5]])
{
if (MAVLINK_MESSAGE_LENGTHS[buffer[5]] == 0) // pass for unknown packets
{
}
else
{
log.InfoFormat("Mavlink Bad Packet (Len Fail) len {0} pkno {1}", buffer.Length, buffer[5]);
if (buffer.Length == 11 && buffer[0] == 'U' && buffer[5] == 0)
{
string message = "Mavlink 0.9 Heartbeat, Please upgrade your AP, This planner is for Mavlink 1.0\n\n";
System.Windows.Forms.CustomMessageBox.Show(message);
throw new Exception(message);
}
return new byte[0];
}
}
if (buffer.Length < 5 || buffer[buffer.Length - 1] != (crc >> 8) || buffer[buffer.Length - 2] != (crc & 0xff))
{
int packetno = -1;
if (buffer.Length > 5)
{
packetno = buffer[5];
}
log.InfoFormat("Mavlink Bad Packet (crc fail) len {0} crc {1} pkno {2}", buffer.Length, crc, packetno);
return new byte[0];
}
try
{
if ((buffer[0] == 'U' || buffer[0] == 254) && buffer.Length >= buffer[1])
{
if (buffer[3] == '3' && buffer[4] == 'D')
{
}
else
{
byte packetSeqNo = buffer[2];
int expectedPacketSeqNo = ((recvpacketcount + 1) % 0x100);
if (buffer[5] == MAVLINK_MSG_ID_SIMSTATE)
{
// sitl injects a packet with a bad sequence number
}
else
{
if (packetSeqNo != expectedPacketSeqNo)
{
synclost++; // actualy sync loss's
int numLost = 0;
if (packetSeqNo < ((recvpacketcount + 1))) // recvpacketcount = 255 then 10 < 256 = true if was % 0x100 this would fail
{
numLost = 0x100 - expectedPacketSeqNo + packetSeqNo;
}
else
{
numLost = packetSeqNo - recvpacketcount;
}
packetslost += numLost;
WhenPacketLost.OnNext(numLost);
log.InfoFormat("lost {0} pkts {1}", packetSeqNo, (int)packetslost);
}
packetsnotlost++;
recvpacketcount = packetSeqNo;
}
WhenPacketReceived.OnNext(1);
// Console.WriteLine(DateTime.Now.Millisecond);
}
//MAVLINK_MSG_ID_GPS_STATUS
//if (temp[5] == MAVLINK_MSG_ID_GPS_STATUS)
// Console.Write(temp[5] + " " + DateTime.Now.Millisecond + " " + packetspersecond[temp[5]] + " " + (DateTime.Now - packetspersecondbuild[temp[5]]).TotalMilliseconds + " \n");
if (double.IsInfinity(packetspersecond[buffer[5]]))
packetspersecond[buffer[5]] = 0;
packetspersecond[buffer[5]] = (((1000 / ((DateTime.Now - packetspersecondbuild[buffer[5]]).TotalMilliseconds) + packetspersecond[buffer[5]]) / 2));
packetspersecondbuild[buffer[5]] = DateTime.Now;
//Console.WriteLine("Packet {0}",temp[5]);
// store packet history
lock (objlock)
{
packets[buffer[5]] = buffer;
}
if (debugmavlink)
DebugPacket(buffer);
if (buffer[5] == MAVLink.MAVLINK_MSG_ID_STATUSTEXT) // status text
{
string logdata = Encoding.ASCII.GetString(buffer, 7, buffer.Length - 7);
int ind = logdata.IndexOf('\0');
if (ind != -1)
logdata = logdata.Substring(0, ind);
log.Info(DateTime.Now + " " + logdata);
if (MainV2.speechEngine != null && MainV2.config["speechenable"] != null && MainV2.config["speechenable"].ToString() == "True")
{
//MainV2.talk.SpeakAsync(logdata);
}
}
getWPsfromstream(ref buffer);
try
{
if (logfile != null && logfile.BaseStream.CanWrite && !logreadmode)
{
lock (logfile)
{
byte[] datearray = BitConverter.GetBytes((UInt64)((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds * 1000));
Array.Reverse(datearray);
logfile.Write(datearray, 0, datearray.Length);
logfile.Write(buffer, 0, buffer.Length);
if (buffer[5] == 0)
{// flush on heartbeat - 1 seconds
logfile.BaseStream.Flush();
rawlogfile.BaseStream.Flush();
}
}
}
}
catch { }
}
}
catch { }
if (buffer[3] == '3' && buffer[4] == 'D')
{
// dont update last packet time for 3dr radio packets
}
else
{
lastvalidpacket = DateTime.Now;
}
// Console.Write((DateTime.Now - start).TotalMilliseconds.ToString("00.000") + "\t" + temp.Length + " \r");
// Console.WriteLine(DateTime.Now.Millisecond + " SR4 " + BaseStream.BytesToRead);
return buffer;
}
///
/// Used to extract mission from log file
///
/// packet
void getWPsfromstream(ref byte[] buffer)
{
if (buffer[5] == MAVLINK_MSG_ID_MISSION_COUNT)
{
// clear old
wps.Clear();
//new PointLatLngAlt[wps.Length];
}
if (buffer[5] == MAVLink.MAVLINK_MSG_ID_MISSION_ITEM)
{
mavlink_mission_item_t wp = buffer.ByteArrayToStructure(6);
if (wp.current == 2)
{
// guide mode wp
GuidedMode = wp;
}
else
{
wps[wp.seq] = wp;
}
Console.WriteLine("WP # {7} cmd {8} p1 {0} p2 {1} p3 {2} p4 {3} x {4} y {5} z {6}", wp.param1, wp.param2, wp.param3, wp.param4, wp.x, wp.y, wp.z, wp.seq, wp.command);
}
}
public PointLatLngAlt getFencePoint(int no, ref int total)
{
byte[] buffer;
MainV2.giveComport = true;
PointLatLngAlt plla = new PointLatLngAlt();
mavlink_fence_fetch_point_t req = new mavlink_fence_fetch_point_t();
req.idx = (byte)no;
req.target_component = compid;
req.target_system = sysid;
// request point
generatePacket(MAVLINK_MSG_ID_FENCE_FETCH_POINT, req);
DateTime start = DateTime.Now;
int retrys = 3;
while (true)
{
if (!(start.AddMilliseconds(500) > DateTime.Now))
{
if (retrys > 0)
{
log.Info("getFencePoint Retry " + retrys + " - giv com " + MainV2.giveComport);
generatePacket(MAVLINK_MSG_ID_FENCE_FETCH_POINT, req);
start = DateTime.Now;
retrys--;
continue;
}
MainV2.giveComport = false;
throw new Exception("Timeout on read - getFencePoint");
}
buffer = readPacket();
if (buffer.Length > 5)
{
if (buffer[5] == MAVLINK_MSG_ID_FENCE_POINT)
{
MainV2.giveComport = false;
mavlink_fence_point_t fp = buffer.ByteArrayToStructure(6);
plla.Lat = fp.lat;
plla.Lng = fp.lng;
plla.Tag = fp.idx.ToString();
total = fp.count;
return plla;
}
}
}
}
public bool setFencePoint(byte index, PointLatLngAlt plla, byte fencepointcount)
{
mavlink_fence_point_t fp = new mavlink_fence_point_t();
fp.idx = index;
fp.count = fencepointcount;
fp.lat = (float)plla.Lat;
fp.lng = (float)plla.Lng;
fp.target_component = compid;
fp.target_system = sysid;
int retry = 3;
while (retry > 0)
{
generatePacket(MAVLINK_MSG_ID_FENCE_POINT, fp);
int counttemp = 0;
PointLatLngAlt newfp = getFencePoint(fp.idx, ref counttemp);
if (newfp.Lat == plla.Lat && newfp.Lng == fp.lng)
return true;
retry--;
}
return false;
}
byte[] readlogPacket()
{
byte[] temp = new byte[300];
sysid = 0;
int a = 0;
while (a < temp.Length && logplaybackfile.BaseStream.Position != logplaybackfile.BaseStream.Length)
{
temp[a] = (byte)logplaybackfile.BaseStream.ReadByte();
//Console.Write((char)temp[a]);
if (temp[a] == ':')
{
break;
}
a++;
if (temp[0] != '-')
{
a = 0;
}
}
//Console.Write('\n');
//Encoding.ASCII.GetString(temp, 0, a);
string datestring = Encoding.ASCII.GetString(temp, 0, a);
//Console.WriteLine(datestring);
long date = Int64.Parse(datestring);
DateTime date1 = DateTime.FromBinary(date);
lastlogread = date1;
int length = 5;
a = 0;
while (a < length)
{
temp[a] = (byte)logplaybackfile.BaseStream.ReadByte();
if (a == 1)
{
length = temp[1] + 6 + 2 + 1;
}
a++;
}
return temp;
}
byte[] readlogPacketMavlink()
{
byte[] temp = new byte[300];
sysid = 0;
//byte[] datearray = BitConverter.GetBytes((ulong)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds);
byte[] datearray = new byte[8];
int tem = logplaybackfile.BaseStream.Read(datearray, 0, datearray.Length);
Array.Reverse(datearray);
DateTime date1 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
UInt64 dateint = BitConverter.ToUInt64(datearray, 0);
try
{
date1 = date1.AddMilliseconds(dateint / 1000);
lastlogread = date1.ToLocalTime();
}
catch { }
MainV2.cs.datetime = lastlogread;
int length = 5;
int a = 0;
while (a < length)
{
temp[a] = (byte)logplaybackfile.ReadByte();
if (temp[0] != 'U' && temp[0] != 254)
{
log.InfoFormat("lost sync byte {0} pos {1}", temp[0], logplaybackfile.BaseStream.Position);
a = 0;
continue;
}
if (a == 1)
{
length = temp[1] + 6 + 2; // 6 header + 2 checksum
}
a++;
}
// set ap type for log file playback
if (temp[5] == 0)
{
mavlink_heartbeat_t hb = temp.ByteArrayToStructure(6);
mavlinkversion = hb.mavlink_version;
aptype = (MAV_TYPE)hb.type;
apname = (MAV_AUTOPILOT)hb.autopilot;
setAPType();
}
return temp;
}
public static bool translateMode(string modein, ref MAVLink.mavlink_set_mode_t mode)
{
//MAVLink09.mavlink_set_mode_t mode = new MAVLink09.mavlink_set_mode_t();
mode.target_system = MainV2.comPort.sysid;
try
{
if (Common.getModes() == typeof(Common.apmmodes))
{
switch (EnumTranslator.GetValue(modein))
{
case (int)Common.apmmodes.MANUAL:
case (int)Common.apmmodes.CIRCLE:
case (int)Common.apmmodes.STABILIZE:
case (int)Common.apmmodes.AUTO:
case (int)Common.apmmodes.RTL:
case (int)Common.apmmodes.LOITER:
case (int)Common.apmmodes.FLY_BY_WIRE_A:
case (int)Common.apmmodes.FLY_BY_WIRE_B:
mode.base_mode = (byte)MAVLink.MAV_MODE_FLAG.CUSTOM_MODE_ENABLED;
mode.custom_mode = (uint)EnumTranslator.GetValue(modein);
break;
default:
MessageBox.Show("No Mode Changed " + modein);
return false;
}
}
else if (Common.getModes() == typeof(Common.ac2modes))
{
switch (EnumTranslator.GetValue(modein))
{
case (int)Common.ac2modes.STABILIZE:
case (int)Common.ac2modes.AUTO:
case (int)Common.ac2modes.RTL:
case (int)Common.ac2modes.LOITER:
case (int)Common.ac2modes.ACRO:
case (int)Common.ac2modes.ALT_HOLD:
case (int)Common.ac2modes.CIRCLE:
case (int)Common.ac2modes.POSITION:
case (int)Common.ac2modes.LAND:
case (int)Common.ac2modes.OF_LOITER:
mode.base_mode = (byte)MAVLink.MAV_MODE_FLAG.CUSTOM_MODE_ENABLED;
mode.custom_mode = (uint)EnumTranslator.GetValue(modein);
break;
default:
MessageBox.Show("No Mode Changed " + modein);
return false;
}
}
}
catch { System.Windows.Forms.MessageBox.Show("Failed to find Mode"); return false; }
return true;
}
public void setAPType()
{
switch (apname)
{
case MAV_AUTOPILOT.ARDUPILOTMEGA:
switch (aptype)
{
case MAVLink.MAV_TYPE.FIXED_WING:
MainV2.cs.firmware = MainV2.Firmwares.ArduPlane;
break;
case MAVLink.MAV_TYPE.QUADROTOR:
MainV2.cs.firmware = MainV2.Firmwares.ArduCopter2;
break;
case MAVLink.MAV_TYPE.GROUND_ROVER:
MainV2.cs.firmware = MainV2.Firmwares.ArduRover;
break;
default:
break;
}
break;
case MAV_AUTOPILOT.UDB:
break;
}
}
}
}