Пример #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void SL_ClientConnected(object sender, SocketAsyncEventArgs e)
        {
            connections = Interlocked.Increment(ref connections);
            Socket s = e.UserToken as Socket;

            System.Net.IPEndPoint ep = (System.Net.IPEndPoint)s.RemoteEndPoint;

            gControl.collog.TraceInformation("New Connection : " + s.RemoteEndPoint.ToString());

            LMInstrument lmi = new LMInstrument(e, ep.Port);

            Instruments.All.Add(lmi);
            // dev note: need a parallel entry in the counting parameters map on the enclosing Measurement for each instrument and it's SR params class instance

            // get the status of the instrument
            LMMMComm.FormatAndSendLMMMCommand(LMComm.LMMMLingo.Tokens.cstatus, 0, Instruments.Active.RankPositionInList(lmi));
        }
Пример #2
0
        // still need to test if this works
        //         typing 'stop' at prompt stops the current cycle, but not the overall processing state, this method should now stop the entire process
        // devnote: Could just use a timer-based check of the token, same as for progress polling into the analyzer
        /// <summary>
        /// send the cancel command to each LMMM, set the instrument state Online to prevent data processing of any additional packets
        /// </summary>
        /// <param name="removeCurLMDataFile">delete the current LM data files created for the current interval</param>
        private void StopLMCAssay(bool removeCurLMDataFile)
        {
            collog.TraceEvent(LogLevels.Info, 0, "Stopping assay...");
            CurState.State = DAQInstrState.Online;

            // stop each instrument in the active list
            foreach (Instrument active in Instruments.Active)
            {
                //This new from USB version incc6, commenting out has no effect on doubles/triples errors hn 9/22/2014
                active.StopAssay(); // for PTR-32 and MCA527

                // send cancel command to the LMMM instruments
                if (active is LMInstrument && (active.id.SRType == InstrType.LMMM))
                {
                    LMInstrument lmi = active as LMInstrument;
                    LMMMComm.FormatAndSendLMMMCommand(LMMMLingo.Tokens.cancel, 0, Instruments.Active.RankPositionInList(lmi)); // send to all active, 1 by 1
                    if (collectingFileData && lmi.file != null)
                    {
                        lmi.file.CloseWriter();
                        if (removeCurLMDataFile)
                        {
                            lmi.file.Delete();
                        }
                    }
                    active.DAQState = DAQInstrState.Online;
                }
                else if (active is SRInstrument)
                {
                    // tell the SR thread handler to cancel it
                    ctrllog.TraceInformation("Stop SR {0}", active.id.Identifier());
                    SRWrangler.StopThread(active as SRInstrument, true);
                    active.DAQState = DAQInstrState.Offline;
                }
            }

            ctrllog.TraceInformation("Assay cancelled");
            NC.App.Loggers.Flush();
        }
Пример #3
0
        /// <summary>
        /// Start an assay on every instrument connected, this is for a single interval only
        /// The LMMM does just one assay from it's POV, and needs to be retold by DAQ here to do the next interval
        /// </summary>
        private int StartLM_SRAssay()
        {
            collog.TraceEvent(LogLevels.Info, 0, "Starting assay...");

            CurState.Measurement.CurrentRepetition++;
            CurState.State = DAQInstrState.ReceivingData;

            numTotalBytes = 0;

            collectingFileData = NC.App.AppContext.LiveFileWrite;

            CurState.StampAssayTime();
            CurState.GenDateTimePrefix(NC.App.AppContext.RootLoc);

            foreach (Instrument active in Instruments.Active)
            {
                if (active is SRInstrument)
                {
                    ctrllog.TraceEvent(LogLevels.Verbose, 999333, "Got SR {0} here", (active as SRInstrument).id.Identifier());
                }
                active.DAQState = DAQInstrState.ReceivingData;

                Cycle cycle = new Cycle(ctrllog);
                cycle.SetUpdatedDataSourceId(active.id); // where the cycle came from, but with updated timestamp
                CurState.Measurement.Add(cycle);         // todo: this mixes the cycles from the different instruments onto one list, gotta change this now that we are at more than one instrument, well you can simply write iterators that select on specific instrument Ids, over the entire list, or use LINQ select * where dsid == whatever syntax on the list
                ctrllog.TraceEvent(LogLevels.Verbose, 93939, "Cycle {0} init", cycle.seq);

                // devnote: file writing is selectable via the UI, and raw analysis should be independently
                // start the file capture
                if (active is LMInstrument)
                {
                    NCCFile.INeutronDataFile f = (active as LMInstrument).PrepOutputFile(CurState.currentDataFilenamePrefix, Instruments.Active.IndexOf(active), collog);
                    active.RDT.StartCycle(cycle, f); // internal handler needs access to the file handle for PTR-32 and MCA-527, but not for LMMM
                    ctrllog.TraceEvent(LogLevels.Verbose, 93939, "Cycle {0}, {1}", cycle.seq, string.IsNullOrEmpty(f.Filename) ? string.Empty: "output file name " + f.Filename);
                }
                else
                {
                    active.RDT.StartCycle(cycle);
                }

                if (CurState.Measurement.CurrentRepetition == 1)
                {
                    //  devnote: with more than one active, these need to be revisited
                    if (active is LMInstrument)
                    {
                        (active as LMInstrument).RDT.SetupCountingAnalyzerHandler(NC.App.Config, active.id.source.TimeBase(active.id.SRType));
                        (active as LMInstrument).RDT.PrepareAndStartCountingAnalyzers(CurState.Measurement.AnalysisParams);
                    }

                    // todo: Measurement Detector List exists but is not integrated with associated Instrument objects here
                    if (active is SRInstrument)
                    {
                        // kick off the thread to try and init the SR
                        SRWrangler.StartSRActionAndWait((active as SRInstrument).id, SRTakeDataHandler.SROp.InitializeSR);
                    }
                    else if (active is LMInstrument && active.id.SRType == InstrType.LMMM)
                    {
                        LMMMComm.FormatAndSendLMMMCommand(LMMMLingo.Tokens.prep, 0, Instruments.All.IndexOf(active));                         // send this config message to this LMMM
                    }

                    // devnote: index might be wrong if some of multiple LMs are disabled via UI. This will require a revisit at integration time
                }
            }

            NC.App.Loggers.Flush();
            FireEvent(EventType.ActionInProgress, this);
            Thread.Sleep(250); // LMMM only: wait for last send to finish, todo could we use EventHandler<SocketAsyncEventArgs> Completed here?

            // PTR-32/MCA-527
            // This loop works for PTR-32 and MCA-527 instruments, based on an improved instrument and control design

            // devnote: rewrite SR and LMMM sections below to use the StartAssay virtual method abstraction for measurement control
            foreach (Instrument instrument in Instruments.Active)
            {
                try {
                    instrument.StartAssay(CurState.Measurement);
                }
                catch (Exception ex) {
                    collog.TraceException(ex);
                }
            }

            // The following sections are for SR and LMMM
            // LMMM
            if (Instruments.Active.HasLMMM()) // send to a plurality of thresholding units, err, I mean, LMMM Instruments
            {
                if (CurState.broadcastGo)     // send go
                {
                    // this has to be sent separately, because linux control is looking for the Arm alone.
                    LMMMComm.FormatAndSendLMMMCommand(LMMMLingo.Tokens.arm); // send to all active

                    Thread.Sleep(250);                                       // allow linux code to setup waiting socket.

                    // broadcast go message to all NCC.App.Config.Net.Subnet addresses. This is the instrument group.
                    LMMMComm.PostLMMMCommand(LMMMLingo.Tokens.go, true);
                }
                else
                {
                    LMMMComm.FormatAndSendLMMMCommand(LMMMLingo.Tokens.go);                     // send to all active
                }
            }

            // SR
            bool srgood = false, hasSR = false;
            // send the start DAQ to every active SR, probably better to do this in the event handler not here
            IEnumerator iter = Instruments.Active.GetSREnumerator();

            while (iter.MoveNext())
            {
                hasSR = true;
                SRInstrument sri = (SRInstrument)iter.Current;
                int          srStatus = 0, measStatus = 0;
                SRWrangler.GetLastStatus(sri.id, ref srStatus, ref measStatus);

                if (measStatus != INCCSR.SUCCESS) // failure means we cannot see or use the SR, so go to the next one, whereas success means it initialized correctly in the InitializeSR step
                {
                    sri.DAQState = DAQInstrState.Offline;
                    continue;
                }

                int status = SRWrangler.StartSRActionAndWait(sri.id, SRTakeDataHandler.SROp.StartSRDAQ); // NEXT: check if pending here is going to be an issue
                if (status == INCCSR.MEAS_CONTINUE)                                                      // the SR started
                {
                    srgood = true;
                    SRWrangler.SetAction(sri.id, SRTakeDataHandler.SROp.WaitForResults); // event handler will pick up results when the internal timer polling in the thread detects results and fires the event
                }
            }
            // need a better test in here to skip all this startup stuff when the SR/LM/cycle init failed
            if (Instruments.Active.Count < 1)
            {
                CurState.Measurement.CurrentRepetition--;
                ctrllog.TraceEvent(LogLevels.Warning, 46, "No active instruments available now");
            }
            else if (hasSR && !srgood)
            {
                CurState.Measurement.CurrentRepetition--;
                ctrllog.TraceEvent(LogLevels.Warning, 46, "No Shift Register is available now");
            }
            else
            {
                if (CurState.Measurement.CurrentRepetition == 1)
                {
                    if (Instruments.Active.Count > 1)
                    {
                        if (Instruments.Active.Count != Instruments.All.Count)
                        {
                            ctrllog.TraceInformation("Using " + Instruments.Active.Count + " of " + Instruments.All.Count + " instruments");
                        }
                        else
                        {
                            ctrllog.TraceInformation("Using " + Instruments.Active.Count + " instruments");
                        }
                    }
                    else
                    {
                        ctrllog.TraceInformation("Using one instrument");
                    }
                }

                string str = "Assay cycle " + CurState.Measurement.CurrentRepetition + " of ";
                if (CurState.Measurement.RequestedRepetitions == 0)
                {
                    str += "a continuous assay starting";
                }
                else
                {
                    str += (CurState.Measurement.RequestedRepetitions + " cycles starting");
                }
                ctrllog.TraceInformation(str);
            }
            if (Instruments.Active.Count > 0)
            {
                FireEvent(EventType.ActionInProgress, this);
                collog.TraceEvent(LogLevels.Verbose, 0, "Started assay with {0} instrument{1}", Instruments.Active.Count, (Instruments.Active.Count > 1 ? "s" : ""));
            }
            return(Instruments.Active.Count);
        }
Пример #4
0
        /// <summary>
        /// Handle data from the client sockets
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void SL_DataReceived(object sender, SocketAsyncEventArgs e)
        {
            Socket s = e.UserToken as Socket;

            System.Net.IPEndPoint ep = (System.Net.IPEndPoint)s.RemoteEndPoint;

            packets = Interlocked.Increment(ref packets);
            // call the specific instrument handler here using the ID.
            // This routine is needed if there are more than one type of instrument.
            // match with port it came from, each connection will have a different port.
            LMInstrument activeInstr = Instruments.Active.MatchByPort(ep.Port);  // dev note: this might be slow, could speed up this by switching to a map rather than a list
            bool         verbose     = gControl.netlog.ShouldTrace(LogLevels.Verbose);

            if (verbose)
            {
                PacketLogSLOW(activeInstr, e);
            }
            if (activeInstr.DAQState == DAQInstrState.ReceivingData)
            {
                activeInstr.NumProcessedRawDataBuffers++;

                if (verbose) /* diag buffer tracing */
                {
                    string temp = string.Format("{0}: bytes {1}, total bytes {2}, LM {3}",
                                                activeInstr.NumProcessedRawDataBuffers, e.BytesTransferred, numTotalBytes, Instruments.Active.IndexOf(activeInstr));
                    gControl.netlog.TraceEvent(LogLevels.Verbose, 686, temp);
                }

                try
                {
                    if (CurState.IsQuitRequested)
                    {
                        throw new AnalysisDefs.CancellationRequestedException();
                    }
                    else if ((e.BytesTransferred % 2) == 0) // EVEN messages are data.
                    {
                        // dev note: file writing is controlled via LiveFileWrite
                        (activeInstr.file as NCCFile.NCDFile).Write(e.Buffer, e.Offset, e.BytesTransferred);

                        try
                        {
                            // this method copies the buffer and sends it on to neutron counting
                            var res = activeInstr.RDT.PassBufferToTheCounters(e.Buffer, e.Offset, e.BytesTransferred);
                            if (res != null) //Handle this error condition as if it is a regular ODD-count packet with the end marker
                            {
                                HandleEndOfCycleProcessing(activeInstr, res);
                            }
                        }
                        catch (Exception ex)
                        {
                            HandleFatalGeneralError(activeInstr, ex);
                        }
                    }
                    else //    ODD - last data is the status message.
                    {
                        try
                        {
                            LMComm.LMMMLingo.Tokens response = LMMMComm.DataPacketResponseMatch(e.Buffer, e.Offset, e.BytesTransferred);
                            // command parsing here should be as fast as possible because data collection is active and may be hampered by even short delays in this section
                            // it is a status message, the last message of an assay
                            if (response == LMComm.LMMMLingo.Tokens.statusdata) // dev note: must be odd length and end with '......' or '......' (old style) or else start with 'Status\r\n' (new style Nov. 2010)
                            {
                                try                                             // // write the last message to the file.This might be a partial data + last message
                                {
                                    (activeInstr.file as NCCFile.NCDFile).Write(e.Buffer, e.Offset, e.BytesTransferred);
                                    (activeInstr.file as NCCFile.NCDFile).CloseWriter();
                                }
                                catch (Exception fex)
                                {
                                    if ((activeInstr.file as NCCFile.NCDFile).stream != null)
                                    {
                                        gControl.netlog.TraceEvent(LogLevels.Error, 642, "{0}: error on close {1}", (activeInstr.file as NCCFile.NCDFile).stream.Name, fex.Message);
                                    }
                                }

                                var res = activeInstr.RDT.PassBufferToTheCounters(e.Buffer, e.Offset, e.BytesTransferred);
                                HandleEndOfCycleProcessing(activeInstr, res);
                            }
                            else if (response == LMComm.LMMMLingo.Tokens.tosenddatasize)                                 // this says how many bytes are going to be sent
                            {
                                numTotalBytes = LMMMComm.ResponseToSendDataSize(e.Buffer, e.Offset, e.BytesTransferred); // t
                                gControl.netlog.TraceEvent(LogLevels.Verbose, 654, "Expecting " + Convert.ToString(numTotalBytes) + " (to sen)");
                            }
                            else if (response == LMComm.LMMMLingo.Tokens.unrecognizeddata) // unrecognized command
                            {
                                string temp = LMMMComm.ResponseUnrecoSample(e.Buffer, e.Offset, e.BytesTransferred);
                                gControl.netlog.TraceInformation(temp);
                            }
                            else // it might be an odd message with some data tacked on the beginning
                            {
                                if (gControl.collectingFileData)
                                {
                                    (activeInstr.file as NCCFile.NCDFile).Write(e.Buffer, e.Offset, e.BytesTransferred);
                                    (activeInstr.file as NCCFile.NCDFile).CloseWriter();
                                }
                                if (response == LMComm.LMMMLingo.Tokens.rates) // somehow got a rates block
                                {
                                    RatesStatus p        = new RatesStatus();
                                    String      received = LMMMComm.NonDataResponse(e.Buffer, e.Offset, e.BytesTransferred);
                                    LMMMComm.SplitRatesReadResponse(received, ref p);
                                    gControl.netlog.TraceInformation("ReceivingData rates {0} on LM {1}:{2}", p.ToString(), Instruments.Active.IndexOf(activeInstr), activeInstr.id.DetectorId);
                                }
                                CurState.State = DAQInstrState.Online;
                                gControl.netlog.TraceInformation("Cycle " + CurState.Measurement.CurrentRepetition + " complete");
                                if ((CurState.Measurement.CurrentRepetition < CurState.Measurement.RequestedRepetitions) || (CurState.Measurement.RequestedRepetitions == 0))
                                {
                                    bool ok = activeInstr.RDT.EndOfCycleProcessing(CurState.Measurement);
                                    if (ok)
                                    {
                                        gControl.FireEvent(EventType.ActionInProgress, gControl);
                                        gControl.StartLM_SRAssay();
                                    }
                                    else
                                    {
                                        gControl.MajorOperationCompleted(); // the overall pend handle used by cmd line
                                    }
                                }
                                else
                                {
                                    gControl.netlog.TraceInformation("All assay cycles completed, but with data in an odd-sized packet");
                                    bool ok = activeInstr.RDT.EndOfCycleProcessing(CurState.Measurement, last: true);
                                    gControl.MajorOperationCompleted(); // the overall pend handle used by cmd line
                                }
                            }
                        }
                        catch (AnalysisDefs.FatalNeutronCountingException fae)  // propagated up from the AnalysisHandler
                        {
                            HandleFatalGeneralError(activeInstr, fae);
                        }
                        catch (AnalysisDefs.CancellationRequestedException)  // thrown from this method
                        {
                            StopActiveAssayImmediately();
                        }
                        catch (Exception oddex)
                        {
                            gControl.netlog.TraceEvent(LogLevels.Error, 643, "Internal error, stopping active processing, {0}: Odd data length handler: {1}",
                                                       activeInstr.NumProcessedRawDataBuffers, oddex.Message);
                            HandleFatalGeneralError(activeInstr, oddex);
                        }
                    }
                }
                catch (AnalysisDefs.CancellationRequestedException)  // thrown from this method
                {
                    StopActiveAssayImmediately();
                }
                if (verbose)
                {
                    gControl.netlog.Flush();
                }
            }
            else if (activeInstr.DAQState == DAQInstrState.Online || activeInstr.DAQState == DAQInstrState.HVCalib) // we are not taking data.
            {
                String received = LMMMComm.NonDataResponse(e.Buffer, e.Offset, e.BytesTransferred);

                if (activeInstr.IsNew())
                {
                    string iname = String.Empty;
                    string type  = InstrType.LMMM.ToString();
                    LMMMComm.SplitBroadcastResponse(received, ref type, ref iname, ref activeInstr.id.version);
                    activeInstr.id.DetectorId = iname;
                    activeInstr.id.SetSRType(type);
                    gControl.netlog.TraceInformation("The new instrument is " + LMLoggers.LognLM.FlattenChars(received));
                    gControl.netlog.TraceInformation(Instruments.All.Count + " instrument(s) online");
                    activeInstr.selected = true;  // this should only be set if there is no UI
                    CurState.State       = DAQInstrState.Online;
                    gControl.FireEvent(EventType.ActionPrep, gControl);
                }
                else
                {
                    // slow parsing in this section is fine because data collection is not occurring
                    LMComm.LMMMLingo.Tokens response = LMMMComm.ResponseMatchPrefix(received);
                    if (response == LMComm.LMMMLingo.Tokens.cstatus) //  it is a status readback
                    {
                        LMMMComm.SplitCStatusResponse(received, ref activeInstr.lmstatus);
                        gControl.netlog.TraceInformation(
                            "cStatus for LM {0}:{1} is dbg:{2}, leds:{3}, input:{4}, HVset:{5}, HV:{6}, LLD Max:{7}, LLD:{8}, (u1:{9})",
                            Instruments.Active.IndexOf(activeInstr), activeInstr.id.DetectorId, activeInstr.lmstatus.debug, activeInstr.lmstatus.leds, activeInstr.lmstatus.inputPath, activeInstr.lmstatus.setpoint, activeInstr.lmstatus.hv,
                            activeInstr.lmstatus.MaxLLD, activeInstr.lmstatus.LLD, activeInstr.lmstatus.u1);
                    }
                    else if (response == LMComm.LMMMLingo.Tokens.hvread) // it is a hv readback
                    {
                        int hv = 0;
                        LMMMComm.SplitHVReadResponse(received, ref hv);
                        gControl.netlog.TraceInformation("HVread {0} volts for LM {1}:{2}", hv,
                                                         Instruments.Active.IndexOf(activeInstr), activeInstr.id.DetectorId);
                    }
                    else if (response == LMComm.LMMMLingo.Tokens.hvcalib) // it is a hv calibration point
                    {
                        HVControl.HVStatus hvst = new HVControl.HVStatus();
                        LMMMComm.SplitHVCalibResponse(received, ref hvst);
                        gControl.AppendHVCalibration(hvst);
                        gControl.netlog.TraceInformation("HVcalib for LM {0}:{1} is [setpt:{2}, read:{3},  . . .]",
                                                         Instruments.Active.IndexOf(activeInstr), activeInstr.id.DetectorId, hvst.HVsetpt, hvst.HVread);
                        gControl.StepHVCalibration();
                    }
                    else if (response == LMComm.LMMMLingo.Tokens.rates) // it is a rates response
                    {
                        RatesStatus p = new RatesStatus();
                        LMMMComm.SplitRatesReadResponse(received, ref p);
                        gControl.netlog.TraceInformation("Rates {0} on LM {1}:{2}", p.ToString(),
                                                         Instruments.Active.IndexOf(activeInstr), activeInstr.id.DetectorId);
                    }
                    else if (response == LMComm.LMMMLingo.Tokens.power) // it is a power status
                    {
                        PowerStatus p = new PowerStatus();
                        LMMMComm.SplitPowerReadResponse(received, ref p);
                        gControl.netlog.TraceInformation("Power AC {0}, Batt {1}, Batt Level {2} on LM {3}:{4}", p.ACPresent, p.batteryPresent, p.batterylevelPct,
                                                         Instruments.Active.IndexOf(activeInstr), activeInstr.id.DetectorId);
                    }
                    else if (response == LMComm.LMMMLingo.Tokens.lld) // LLD status
                    {
                        int lld = 0;
                        LMMMComm.SplitLLDReadResponse(received, ref lld);
                        gControl.netlog.TraceInformation("LLD {0} on LM {1}:{2}", lld,
                                                         Instruments.Active.IndexOf(activeInstr), activeInstr.id.DetectorId);
                    }
                    else // RR: this could be binary data if you cancel an assay and linux is sending a buffer.
                    // RR: this is a large amount of data and we don't want it displayed.
                    // tbd RR: figure out how to turn this back on when data is finished dumping.
                    {
                        if (verbose)
                        {
                            PacketLogSLOW(activeInstr, e);
                        }
                    }
                }
                if (verbose)
                {
                    gControl.netlog.Flush();
                }
            }
        }