internal void updateStats(DataSources.DataSourcePacket data)
        {
            Dispatcher.Invoke(new Action(() =>
            {
                if (data.speed_ms < ushort.MaxValue)
                {
                    if (AntPlusRacerConfig.getInstance().displayMph)
                    {
                        Label_Speed.Content = String.Format("{0:0.0}mph", data.speed_ms * 2.237);
                    }
                    else   //else use real measurement units
                    {
                        Label_Speed.Content = String.Format("{0:0.0}kph", data.speed_ms * 3.6);
                    }
                }

                if (data.power != ushort.MaxValue)
                {
                    Label_Power.Content = String.Format("{0:0}W", data.power);
                }

                if (data.cadence != -1)
                {
                    updateCadence(data.cadence);
                }
            }));
        }
示例#2
0
        public RaceFactoryPanel(Action <RaceDetails> raceOutputRcvr)
        {
            InitializeComponent();
            raceRcvr = raceOutputRcvr;

            if (AntPlusRacerConfig.getInstance().autoLoadAvailableRaceSourcesForRace)
            {
                AntPlusDevMgr antMgr = AntConfigPanel.accessInstance().antMgr;
                for (int i = 0; i < antMgr.deviceList.Count; ++i)
                {
                    AntPlusDevMgr.AntPlus_Connection dev = antMgr.deviceList[i];
                    //Skip devices in use
                    if (dev.dataSource.isInUse || dev.getConnStatus() != AntPlusDevMgr.AntPlus_Connection.ConnState.Connected || isDataSourceReserved(dev.dataSource))
                    {
                        continue;
                    }
                    else
                    {
                        configureRacer(0xFF, dev.dataSource, AntPlusRacerConfig.getInstance().getDefaultRaceTrack(dev.dataSource.getSportType()).distance);
                    }
                }
                if (configuredRacers.Count == 0)
                {
                    DisplayRacerList();
                }
            }
            else
            {
                DisplayRacerList();
            }

            ComboBox_RaceLength.SizeChanged += new SizeChangedEventHandler((sender, args) => comboBoxAutoLblFontSize(sender as ComboBox));
        }
示例#3
0
        public void showRaceFactory()
        {
            prepareForPanelChange(true);
            raceConfig = null;

            RaceFactoryPanel toAdd;

            if (ss_isActive && ss_savedPanel != null)
            {
                toAdd       = ss_savedPanel;
                ss_isActive = false;
            }
            else
            {
                toAdd = new RaceFactoryPanel(factoryComplete);
            }

            Grid_Content.Children.Add(toAdd);
            PanelState = panelState.RaceFactory;

            ss_lastActivity = DateTime.Now;

            if (AntPlusRacerConfig.getInstance().RecordScreenSaverTimeout_negativeIsOff > 0)
            {
                ss_ScreenSaverTimer.Start();
            }
        }
示例#4
0
 void recordDisplayScreenSaver_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
 {
     if (DateTime.Now.Subtract(ss_lastActivity).TotalSeconds > AntPlusRacerConfig.getInstance().RecordScreenSaverTimeout_negativeIsOff)
     {
         lock (ss_ScreenSaverTimer)
         {
             if (!ss_isActive)
             {
                 ss_lastActivity    = DateTime.Now;
                 ss_ignoreFirstMove = true;
                 ss_isActive        = true;
                 Dispatcher.Invoke((Action)showRecords);
                 PanelState = panelState.ScreenSaverRecordDisplay;
             }
         }
     }
 }
示例#5
0
        private void populateDistanceBox(racerSportType sport)
        {
            ComboBox_RaceLength.Items.Clear();

            RacerDetails selectedRacer = null;

            if (racerIndexUnderConfig >= 0)
            {
                selectedRacer = configuredRacers[racerIndexUnderConfig];
                ComboBox_RaceLength.Items.Add(new Label()
                {
                    Content = selectedRacer.targetValue.ToString() + "m track"
                });
            }

            //Add all available values
            foreach (AntPlusRacerConfig.RaceTrack i in AntPlusRacerConfig.getInstance().enabledRaceTracks)
            {
                if (i.sportType == sport)
                {
                    //Skip the current value because we already added it
                    if (selectedRacer != null && selectedRacer.targetValue == i.distance)
                    {
                        continue;
                    }

                    ComboBox_RaceLength.Items.Add(new Label()
                    {
                        Content = i.distance.ToString() + "m track"
                    });
                }
            }

            if (ComboBox_RaceLength.Items.Count == 0)
            {
                ComboBox_RaceLength.Items.Add(new Label()
                {
                    Content = "499m track"
                });
            }

            ComboBox_RaceLength.SelectedIndex = 0;
            comboBoxAutoLblFontSize(ComboBox_RaceLength);
        }
示例#6
0
        private AntConfigPanel()
        {
            InitializeComponent();
            antMgr = new AntPlusDevMgr();

            ListBox_statusPanelHolder.Items.Clear();
            Binding widthBind = new Binding("ActualWidth");

            widthBind.Source = ListBox_statusPanelHolder;
            foreach (AntPlusDevMgr.AntPlus_Connection i in antMgr.deviceList)
            {
                Fit_ConfigPanelDevice pnl = new Fit_ConfigPanelDevice(i);
                pnl.SetBinding(Fit_ConfigPanelDevice.WidthProperty, widthBind);
                ListBox_statusPanelHolder.Items.Add(pnl);
            }


            if (AntPlusRacerConfig.getInstance().remoteControlDevNum_negativeIsOff > 0)
            {
                Grid.SetRow(RacerRemoteControl.getRemoteStatus(), 1);
                Grid_Main.Children.Add(RacerRemoteControl.getRemoteStatus());
            }
        }
示例#7
0
        private void finishRaceAsync()
        {
            isRaceFinished = true;

            raceTock.Stop();
            if (target_type == targetType.Meters)
            {
                raceTimer.Stop();
            }

            if (!AntPlusRacerConfig.getInstance().keepRecords)
            {
                sleepCheckStop(6000);    //wait longer without records because they won't see the scores again
            }
            else
            {
                //Allow time to view the result before we switch screens
                if (AntPlusRacerConfig.getInstance().fastRecords_noNames)
                {
                    sleepCheckStop(1000);
                }
                else
                {
                    sleepCheckStop(3000);
                }

                //Sort racers by finish result so that the saved indexes from the post racepanel are consistent
                racerDetails.Sort((x, y) => Comparer <Double> .Default.Compare(x.finishResult, y.finishResult));

                //Save the results of any human racers
                List <KeyValuePair <TrackRecords.TrackRecordList, int> > savedRecords = new List <KeyValuePair <TrackRecords.TrackRecordList, int> >();
                System.Threading.AutoResetEvent recordSaveDone = new System.Threading.AutoResetEvent(false);
                foreach (RacerDetails i in racerDetails)
                {
                    if (i.dataSource.isHuman)
                    {
                        if (AntPlusRacerConfig.getInstance().fastRecords_noNames)
                        {
                            i.racerRecordInfo = new TrackRecords.RecordData()
                            {
                                FirstName = i.dataSource.getSourceName()
                            };
                        }

                        if (i.racerRecordInfo != null) //If we have preset data, save the record automatically
                        {
                            i.racerRecordInfo.DataSourceName = i.dataSource.getSourceName();
                            i.racerRecordInfo.recordValue    = i.finishResult;
                            TrackRecords.TrackRecordList list = TrackRecords.RecordDatabase.getInstance().getTrackRecordList(i.dataSource.getSportType(), i.targetValue);
                            int pos = TrackRecords.PostRacePanel.saveRacerRecord(list, i.racerRecordInfo);
                            savedRecords.Add(new KeyValuePair <TrackRecords.TrackRecordList, int>(list, pos));
                        }
                        else
                        {
                            OwningDisplayPanel.Dispatcher.Invoke((Action <RacerDetails, Action <TrackRecords.TrackRecordList, int> >)OwningDisplayPanel.showPostRacePanel,
                                                                 i, new Action <TrackRecords.TrackRecordList, int>(
                                                                     (list, pos) =>
                            {
                                savedRecords.Add(new KeyValuePair <TrackRecords.TrackRecordList, int>(list, pos));
                                recordSaveDone.Set();
                            }));

                            //Sleep until post race panel is done
                            System.Threading.WaitHandle.WaitAny(new System.Threading.WaitHandle[] { cancelAsyncToken.Token.WaitHandle, recordSaveDone });
                        }
                        cancelAsyncToken.Token.ThrowIfCancellationRequested();
                    }
                }

                //Yes, there are simpler ways to correlate the lists. But why not try and learn how to use new things?
                Lookup <TrackRecords.TrackRecordList, int> recordLists = (Lookup <TrackRecords.TrackRecordList, int>)savedRecords.ToLookup(k => k.Key, e => e.Value);
                foreach (IGrouping <TrackRecords.TrackRecordList, int> trackList in recordLists)
                {
                    OwningDisplayPanel.Dispatcher.Invoke((Action <TrackRecords.TrackRecordList, List <int> >)OwningDisplayPanel.showResult, trackList.Key, trackList.ToList());
                    //Wait to view this list for a moment
                    if (AntPlusRacerConfig.getInstance().fastRecords_noNames)
                    {
                        sleepCheckStop(1000);
                    }
                    else
                    {
                        sleepCheckStop(5000);
                    }
                }
            }

            OwningDisplayPanel.Dispatcher.Invoke((Action)OwningDisplayPanel.showRaceFactory);   //Now, back to start a new race
        }
示例#8
0
        private void startRaceAsync()
        {
            notFinishedHumanRacers = 0;
            foreach (RacerDetails i in racerDetails)
            {
                i.dataSource.reset();
                OwningDisplayPanel.Dispatcher.Invoke((Action)i.racePanel.resetDisplay, System.Windows.Threading.DispatcherPriority.Loaded);

                if (i.dataSource.isHuman)
                {
                    ++notFinishedHumanRacers;
                }
            }

            if (!AntPlusRacerConfig.getInstance().quickStart_noCountdown)
            {
                //Display names

                for (int i = 0; i < racerDetails.Count; ++i)
                {
                    racerDetails[i].racePanel.makeAnnouncement(racerDetails[i].racer_displayname);
                    sleepCheckStop(1000);
                }
                sleepCheckStop(1000);

                //Display target values
                for (int i = 0; i < racerDetails.Count; ++i)
                {
                    racerDetails[i].racePanel.makeAnnouncement(" ");
                    racerDetails[i].racePanel.makeAnnouncement(racerDetails[i].targetValue.ToString() + " " + target_type);
                }
                sleepCheckStop(2000);

                //Set Displays to Blank
                for (int i = 0; i < racerDetails.Count; ++i)
                {
                    racerDetails[i].racePanel.makeAnnouncement(" ");
                }

                //Countdown (only on top screen)
                racerDetails[0].racePanel.makeAnnouncement("Ready?");
                sleepCheckStop(2000);
                racerDetails[0].racePanel.makeAnnouncement("3");
                sleepCheckStop(1000);
                racerDetails[0].racePanel.makeAnnouncement("2");
                sleepCheckStop(1000);
                racerDetails[0].racePanel.makeAnnouncement("1");
                sleepCheckStop(1000);
            }

            //TODO: qc could check speed of fit equip to make sure no one takes a running start
            racerDetails[0].racePanel.makeAnnouncement("GO!");

            for (int i = 0; i < racerDetails.Count; ++i)
            {
                int a = i;
                racerDetails[i].dataSource.start((Action <DataSourcePacket>)((x) => dataSourceUpdating(a, x)));
            }

            //Start the timer(s)
            raceTock.Start();

            if (target_type == targetType.Meters)
            {
                raceTimer.Start();
            }

            //Clear the countdown display
            sleepCheckStop(1000);

            //Clear Displays
            for (int i = 0; i < racerDetails.Count; ++i)
            {
                racerDetails[i].racePanel.makeAnnouncement("");
            }
        }
        private void decodeRaceControlCmd(RacePanel selectedPanel, byte[] lastMsgBytes)
        {
            switch (lastMsgBytes[3])
            {
            case 0:     //start
            {
                if (selectedPanel.PanelState != RacePanel.panelState.RaceFactory)
                {
                    sendResponse(RemoteControlReturnCodes.Error_PanelInWrongState, lastMsgBytes);
                    return;
                }

                RaceFactoryPanel factoryPanel = selectedPanel.Grid_Content.Children[0] as RaceFactoryPanel;
                if (!factoryPanel.startRace())
                {
                    sendResponse(RemoteControlReturnCodes.Error_RacersNotConfigured, lastMsgBytes);
                    return;
                }
                sendResponse(RemoteControlReturnCodes.Success, lastMsgBytes);
                return;
            }

            case 1:     //restart
            {
                if (selectedPanel.PanelState != RacePanel.panelState.Racing)
                {
                    sendResponse(RemoteControlReturnCodes.Error_PanelInWrongState, lastMsgBytes);
                    return;
                }

                selectedPanel.raceConfig.disposeRace();
                selectedPanel.raceConfig = new RaceDetails(selectedPanel.raceConfig.racerDetails, selectedPanel.raceConfig.target_type);
                selectedPanel.raceConfig.startRace(selectedPanel);
                sendResponse(RemoteControlReturnCodes.Success, lastMsgBytes);
                return;
            }

            case 2:     //cancel race
            {
                if (selectedPanel.PanelState != RacePanel.panelState.RaceFactory &&
                    selectedPanel.PanelState != RacePanel.panelState.Racing &&
                    selectedPanel.PanelState != RacePanel.panelState.PostRaceDisplay &&
                    selectedPanel.PanelState != RacePanel.panelState.PostRaceResults)
                {
                    sendResponse(RemoteControlReturnCodes.Error_PanelInWrongState, lastMsgBytes);
                    return;
                }

                selectedPanel.showRaceFactory();
                sendResponse(RemoteControlReturnCodes.Success, lastMsgBytes);
                return;
            }

            case 3:     //get current racer list
            {
                if (selectedPanel.PanelState != RacePanel.panelState.RaceFactory &&
                    selectedPanel.PanelState != RacePanel.panelState.Racing &&
                    selectedPanel.PanelState != RacePanel.panelState.PostRaceDisplay &&
                    selectedPanel.PanelState != RacePanel.panelState.PostRaceResults)
                {
                    sendResponse(RemoteControlReturnCodes.Error_PanelInWrongState, lastMsgBytes);
                    return;
                }


                List <RacerDetails> racerList;
                if (selectedPanel.PanelState == RacePanel.panelState.RaceFactory)
                {
                    racerList = ((RaceFactoryPanel)selectedPanel.Grid_Content.Children[0]).configuredRacers;
                }
                else
                {
                    racerList = selectedPanel.raceConfig.racerDetails;
                }


                List <byte> retMsg = new List <byte> {
                    (byte)racerList.Count
                };
                for (byte i = 0; i < racerList.Count; ++i)
                {
                    RacerDetails racer = racerList[i];
                    retMsg.Add(i);
                    retMsg.Add(racer.dataSource.uid);
                    retMsg.Add((byte)((ushort)racer.targetValue & 0xFF));
                    retMsg.Add((byte)(((ushort)racer.targetValue & 0xFF00) >> 8));
                    ushort curDistance = (ushort)racer.dataSource.getCurrentDistance();
                    retMsg.Add((byte)((ushort)curDistance & 0xFF));
                    retMsg.Add((byte)(((ushort)curDistance & 0xFF00) >> 8));
                    if (racer.racerRecordInfo != null)
                    {
                        if (!String.IsNullOrWhiteSpace(racer.racerRecordInfo.FirstName))
                        {
                            retMsg.Add(1);
                            retMsg.Add((byte)racer.racerRecordInfo.FirstName.Length);
                            retMsg.AddRange(UTF8Encoding.ASCII.GetBytes(racer.racerRecordInfo.FirstName));
                        }
                        if (!String.IsNullOrWhiteSpace(racer.racerRecordInfo.LastName))
                        {
                            retMsg.Add(2);
                            retMsg.Add((byte)racer.racerRecordInfo.LastName.Length);
                            retMsg.AddRange(UTF8Encoding.ASCII.GetBytes(racer.racerRecordInfo.LastName));
                        }
                        if (!String.IsNullOrWhiteSpace(racer.racerRecordInfo.PhoneNumber))
                        {
                            retMsg.Add(3);
                            retMsg.Add((byte)racer.racerRecordInfo.PhoneNumber.Length);
                            retMsg.AddRange(UTF8Encoding.ASCII.GetBytes(racer.racerRecordInfo.PhoneNumber));
                        }
                        if (!String.IsNullOrWhiteSpace(racer.racerRecordInfo.Email))
                        {
                            retMsg.Add(4);
                            retMsg.Add((byte)racer.racerRecordInfo.Email.Length);
                            retMsg.AddRange(UTF8Encoding.ASCII.GetBytes(racer.racerRecordInfo.Email));
                        }
                    }
                    retMsg.Add(0);          //Null term options list
                }
                sendResponse(RemoteControlReturnCodes.Success, lastMsgBytes, retMsg);
                return;
            }

            case 4:     //Config race
            {
                if (selectedPanel.PanelState != RacePanel.panelState.RaceFactory)
                {
                    if (selectedPanel.PanelState == RacePanel.panelState.ScreenSaverRecordDisplay)
                    {
                        selectedPanel.Dispatcher.Invoke((Action)selectedPanel.showRaceFactory);
                    }
                    else
                    {
                        sendResponse(RemoteControlReturnCodes.Error_PanelInWrongState, lastMsgBytes);
                        return;
                    }
                }

                selectedPanel.ss_lastActivity = DateTime.Now.Add(new TimeSpan(0, 0, 5));            //Give ourselves 5 seconds of extra time before screensaver to process ant messages
                RaceFactoryPanel factoryPanel = selectedPanel.Grid_Content.Children[0] as RaceFactoryPanel;

                if (lastMsgBytes[5] == 0xFF)
                {
                    if (factoryPanel.removeRacer(lastMsgBytes[4]))
                    {
                        sendResponse(RemoteControlReturnCodes.Success, lastMsgBytes);
                        return;
                    }
                    else
                    {
                        sendResponse(RemoteControlReturnCodes.Error_RacerDoesntExist, lastMsgBytes);
                        return;
                    }
                }

                byte sourceID = lastMsgBytes[5];

                DataSources.DataSourceBase dataSrc = null;
                foreach (AntPlusDevMgr.AntPlus_Connection i in AntConfigPanel.accessInstance().antMgr.deviceList)
                {
                    if (i.dataSource.uid == sourceID)
                    {
                        dataSrc = i.dataSource;
                        if (i.getConnStatus() != AntPlusDevMgr.AntPlus_Connection.ConnState.Connected)
                        {
                            sendResponse(RemoteControlReturnCodes.Error_DataSourceNotConnected, lastMsgBytes);
                            return;
                        }
                        break;
                    }
                }
                if (dataSrc == null)
                {
                    sendResponse(RemoteControlReturnCodes.Error_DataSourceDoesntExist, lastMsgBytes);
                    return;
                }

                double trackDist = 0;
                //Get the default (first) track for the given sport type
                foreach (AntPlusRacerConfig.RaceTrack i in AntPlusRacerConfig.getInstance().enabledRaceTracks)
                {
                    if (i.sportType == dataSrc.getSportType())
                    {
                        trackDist = i.distance;
                        break;
                    }
                }

                //decode options
                string firstName = null;
                string lastName  = null;
                string phoneNum  = null;
                string emailAdr  = null;
                int    curPos    = 6;
                while (curPos < lastMsgBytes.Length && lastMsgBytes[curPos] != 0)         //0 is the end of list marker
                {
                    int option = lastMsgBytes[curPos];
                    switch (option)
                    {
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                        int    strLength = lastMsgBytes[curPos + 1];
                        string str       = UTF8Encoding.ASCII.GetString(lastMsgBytes.Skip(curPos + 2).Take(strLength).ToArray());
                        switch (option)
                        {
                        case 1:
                            firstName = str;
                            break;

                        case 2:
                            lastName = str;
                            break;

                        case 3:
                            phoneNum = str;
                            break;

                        case 4:
                            emailAdr = str;
                            break;
                        }
                        curPos += 2 + strLength;
                        break;

                    default:
                        sendResponse(RemoteControlReturnCodes.Error_CmdFormatWrong, lastMsgBytes);
                        return;
                    }
                }

                if (curPos >= lastMsgBytes.Length)          //If we ended without hitting the end of the list
                {
                    sendResponse(RemoteControlReturnCodes.Error_CmdFormatWrong, lastMsgBytes);
                    return;
                }

                //Finally create/change the racer
                int ret = factoryPanel.configureRacer(lastMsgBytes[4], dataSrc, trackDist, firstName, lastName, phoneNum, emailAdr);

                if (ret == 0)
                {
                    sendResponse(RemoteControlReturnCodes.Success, lastMsgBytes);
                }
                else if (ret == -1)
                {
                    sendResponse(RemoteControlReturnCodes.Error_DataSourceInUse, lastMsgBytes);
                }
                else if (ret == -2)
                {
                    sendResponse(RemoteControlReturnCodes.Error_RacerDoesntExist, lastMsgBytes);
                }
                return;
            }

            default:
                sendResponse(RemoteControlReturnCodes.Error_CmdFormatWrong, lastMsgBytes);
                return;
            }
        }
示例#10
0
        public AntPlusDevMgr()
        {
            if (antStick == null)
            {
                ANT_Common.enableDebugLogs();
                findUsableAntDevice();
            }

            if (AntPlusRacerConfig.getInstance().remoteControlDevNum_negativeIsOff > 0)
            {
                numChannelsForDevices = antStick.getNumChannels() - 1;
                RacerRemoteControl.startRemoteControl(antStick.getChannel(numChannelsForDevices));
            }
            else
            {
                numChannelsForDevices = antStick.getNumChannels();
            }

            //Add all devices from config
            foreach (AntPlusRacerConfig.RacerInput i in AntPlusRacerConfig.getInstance().enabledRacerInputs)
            {
                switch (i.type)
                {
                case AntPlusRacerConfig.RacerInputType.ant_BikeCad_UsingSpd:
                    ds_AntPlus_BikeSpd spdOnly = new ds_AntPlus_BikeSpd();
                    deviceList.Add(new AntPlus_Connection(spdOnly));
                    deviceList.Add(new AntPlus_Connection(new ds_AntPlus_BikeCad_UsingSpd(spdOnly)));
                    break;

                case AntPlusRacerConfig.RacerInputType.ant_BikeCadAndSpd:
                    deviceList.Add(new AntPlus_Connection(new ds_AntPlus_BikeSpdCad()));
                    break;

                case AntPlusRacerConfig.RacerInputType.ant_BikeSpd:
                    deviceList.Add(new AntPlus_Connection(new ds_AntPlus_BikeSpd()));
                    break;

                case AntPlusRacerConfig.RacerInputType.ant_FitEqpmt:
                    deviceList.Add(new AntPlus_Connection(new ds_AntPlus_Fit()));
                    break;

                case AntPlusRacerConfig.RacerInputType.ant_StrideSDM:
                    deviceList.Add(new AntPlus_Connection(new ds_AntPlus_StrideSDM()));
                    break;

                default:        //Not one of the ant types, ignore
                    break;
                }

                if (i.defaultDeviceId != 0)
                {
                    deviceList.Last().dataSource.searchProfile.deviceNumber = i.defaultDeviceId;
                }

                if (!String.IsNullOrWhiteSpace(i.displayName))
                {
                    deviceList.Last().dataSource.customSourceName = i.displayName;
                }
            }

            startNextSearch();
        }