Beispiel #1
0
        /// <summary>
        /// Execute this request and wait for a valid response.
        /// </summary>
        /// <param name="lb">The locobuffer to execute on</param>
        /// <param name="validateResponse">Predicate used to filter our the valid response</param>
        /// <param name="timeout">Timeout in milliseconds to wait for a valid response</param>
        public T ExecuteAndWaitForResponse <T>(LocoBuffer lb, Predicate <T> validateResponse, int timeout)
            where T : Message
        {
            object waitLock = new object();
            T      result   = null;

            using (var handler = lb.AddHandler((raw, msg) => {
                var response = msg as T;
                if ((response != null) && (validateResponse(response)))
                {
                    // We've got the response we we're waiting for
                    lock (waitLock)
                    {
                        result = response;
                        Monitor.PulseAll(waitLock);
                    }
                    return(true);
                }
                return(false);
            }))
            {
                // Execute the request now
                Execute(lb);

                // Wait for a result
                lock (waitLock)
                {
                    if (result == null)
                    {
                        Monitor.Wait(waitLock, timeout);
                    }
                }
            }
            return(result);
        }
Beispiel #2
0
 /// <summary>
 /// Default ctor
 /// </summary>
 public LocoNet(LocoBuffer lb, LocoNetConfiguration configuration)
 {
     this.lb = lb;
     this.configuration = configuration;
     state = new LocoNetState(lb);
     unknownLocoIoDetector = new UnknownLocoIODetector(this);
 }
 /// <summary>
 /// Default ctor
 /// </summary>
 internal AsyncLocoBuffer(Control ui, LocoBuffer lb)
 {
     this.ui = ui;
     this.lb = lb;
     var thread = new Thread(Run);
     thread.Start();
 }
        /// <summary>
        /// Read the given set of SV values into configs.
        /// </summary>
        public void Read(LocoBuffer lb, IEnumerable<SVConfig> configs)
        {
            var list = configs.ToList();
            list.Sort();

            foreach (var iterator in configs)
            {
                var config = iterator;
                byte value;
                config.Valid = TryReadSV(lb, config.Index, out value);
                config.Value = value;
            }
        }
Beispiel #5
0
        /// <summary>
        /// Default ctor
        /// </summary>
        public LocoBufferCommandStationState(ILocoBufferCommandStation entity, RailwayState railwayState, string[] addressSpaces)
            : base(entity, railwayState, addressSpaces)
        {
            var splb = new SerialPortLocoBuffer();

            splb.PortName      = entity.ComPortName;
            lb                 = splb;
            lb.PreviewMessage += MessageProcessor;
            client             = new Client(lb, railwayState, this, railwayState.Dispatcher, Log);
            client.Idle       += (s, x) =>
            {
                networkIdle = true;
                RefreshIdle();
            };
        }
        /// <summary>
        /// Write a single SV variable at the given index with the given value.
        /// </summary>
        internal bool ChangeAddress(LocoBuffer lb, int address, int subAddress)
        {
            var cmd = new PeerXferRequest1
            {
                Command = PeerXferRequest.Commands.Write,
                SvAddress = 1,
                DestinationLow =this.address.Address,
                SubAddress = this.address.SubAddress,
                Data1 = (byte)address,
            };
            var result = cmd.ExecuteAndWaitForResponse<PeerXferResponse>(
                lb,
                x => ((x.SvAddress == 1) && (x.OriginalCommand == PeerXferRequest.Commands.Write)),
                timeout);

            if (result == null)
                throw new TimeoutException("Program index 1 failed");

            cmd = new PeerXferRequest1
            {
                Command = PeerXferRequest.Commands.Write,
                SvAddress = 2,
                DestinationLow = this.address.Address,
                SubAddress = this.address.SubAddress,
                Data1 = (byte)subAddress,
            };
            result = cmd.ExecuteAndWaitForResponse<PeerXferResponse>(
                lb,
                x => ((x.SvAddress == 2) && (x.OriginalCommand == PeerXferRequest.Commands.Write)),
                timeout);

            if (result == null)
                throw new TimeoutException("Program index 2 failed");

            return true;
        }
        /// <summary>
        /// Set the speed of a switch.
        /// </summary>
        /// <param name="value">Between 1 and 4</param>
        internal void SetSpeed(LocoBuffer lb, int value)
        {
            if ((value < 1) || (value > 4))
            {
                throw new ArgumentException("Value must be between 1 and 4");
            }

            EnterProgrammingMode(lb);

            SendNibble(lb, 0x05); // Command
            SendNibble(lb, SpeedMasks[value - 1] & 0x07); // LSB
            SendNibble(lb, (SpeedMasks[value - 1] >> 3) & 0x07); // MSB
        }
 /// <summary>
 /// Create and start a new processor
 /// </summary>
 public ReceiveProcessor(LocoBuffer lb)
 {
     this.lb     = lb;
     this.thread = new Thread(OnRun);
     this.thread.Start();
 }
 /// <summary>
 /// Change the type of locobuffer.
 /// </summary>
 private void OnChangeLocoBufferType(object sender, EventArgs e)
 {
     if (rbSerialPort.Checked)
     {
         if (!(LocoBuffer is SerialPortLocoBuffer))
             LocoBuffer = new SerialPortLocoBuffer();
     }
     else if (rbTcp.Checked)
     {
         if (!(LocoBuffer is TcpLocoBuffer))
             LocoBuffer = new TcpLocoBuffer();
     }
     else if (rbUdp.Checked)
     {
         if (!(LocoBuffer is UdpLocoBuffer))
             LocoBuffer = new UdpLocoBuffer();
     }
 }
Beispiel #10
0
 /// <summary>
 /// Execute the message on the given buffer
 /// </summary>
 public abstract void Execute(LocoBuffer lb);
 /// <summary>
 /// Set all bits to 0.
 /// </summary>
 internal void BitsToZero(LocoBuffer lb)
 {
     if (programmingMode)
     {
         throw new InvalidOperationException("Only valid in normal mode");
     }
     SetB4(lb, false);
     SetB3(lb, false);
     SetB2(lb, false);
     SetB1(lb, false);
 }
        /// <summary>
        /// Send a 3-bits nibble.
        /// </summary>
        private void SendNibble(LocoBuffer lb, int value)
        {
            // Lower b4 first
            SetB4(lb, false);

            // Set b1
            SetB1(lb, (value & 0x01) != 0);
            // Set b2
            SetB2(lb, (value & 0x02) != 0);
            // Set b3
            SetB3(lb, (value & 0x04) != 0);

            // Raise B4 to transmit
            SetB4(lb, true);

            // Wait a while
            Thread.Sleep(20);

            // Lower B4 to avoid duplication
            SetB4(lb, false);

            // Wait a while
            Thread.Sleep(5);
        }
Beispiel #13
0
 /// <summary>
 /// Execute the message on the given buffer
 /// </summary>
 public override void Execute(LocoBuffer lb)
 {
     lb.Send(this, CreateMessage());
 }
Beispiel #14
0
 /// <summary>
 /// Write a single SV variable at the given index with the given value.
 /// </summary>
 internal bool WriteSV(LocoBuffer lb, int index, byte value)
 {
     var cmd = new PeerXferRequest1
     {
         Command = PeerXferRequest.Commands.Write,
         SvAddress = index,
         DestinationLow = address.Address,
         SubAddress = address.SubAddress,
         Data1 = value,
     };
     var result = cmd.ExecuteAndWaitForResponse<PeerXferResponse>(
         lb,
         x => (address.Equals(x.Source) && (x.SvAddress == index) && (x.OriginalCommand == PeerXferRequest.Commands.Write)),
         timeout);
     return (result != null) && (result.Data1 == value);
 }
Beispiel #15
0
        /// <summary>
        /// Write the given set of SV values
        /// </summary>
        internal void Write(LocoBuffer lb, IEnumerable<SVConfig> configs)
        {
            var list = configs.ToList();
            list.Sort();

            foreach (var config in configs)
            {
                var ok = false;
                for (int attempt = 0; !ok && (attempt < ATTEMPTS); attempt++)
                {
                    // Write
                    ok = WriteSV(lb, config.Index, config.Value);

                    // Wait a while
                    if (!ok)
                    {
                        Thread.Sleep(100);
                    }
                }
                if (!ok)
                {
                    throw new ProgramException(string.Format("Failed to write SV {0}", config.Index));
                }
            }
        }
Beispiel #16
0
        /// <summary>
        /// Read a single SV variable at the given index.
        /// </summary>
        internal bool TryReadSV(LocoBuffer lb, int index, out byte value)
        {
            var cmd = new PeerXferRequest1
                          {
                              Command = PeerXferRequest.Commands.Read,
                              SvAddress = index,
                              DestinationLow = address.Address,
                              SubAddress = address.SubAddress,
                          };

            var result = cmd.ExecuteAndWaitForResponse<PeerXferResponse>(
                lb,
                x => (address.Equals(x.Source) && (x.SvAddress == index) && (x.OriginalCommand == PeerXferRequest.Commands.Read)),
                timeout);
            if (result != null)
            {
                value = result.Data1;
                return true;
            }
            value = 0;
            return false;
        }
        /// <summary>
        /// Set the target turnout
        /// </summary>
        internal void SetTarget(LocoBuffer lb)
        {
            EnterProgrammingMode(lb);

            SendNibble(lb, 0x01); // Command
            SendNibble(lb, Turnout - 1); // Turnout encoded as 0-3
        }
 /// <summary>
 /// Execute the given request.
 /// </summary>
 private static void Execute(LocoBuffer lb, Request request)
 {
     request.Execute(lb);
 }
Beispiel #19
0
 /// <summary>
 /// Default ctor
 /// </summary>
 internal HandlerRegistration(LocoBuffer lb, MessageHandler handler)
 {
     this.lb = lb;
     this.handler = handler;
 }
 private void SetB4(LocoBuffer lb, bool on)
 {
     Execute(lb, new SwitchRequest { Address = Address4, Direction = on, Output = true });
 }
 /// <summary>
 /// Default ctor
 /// </summary>
 /// <param name="lb"></param>
 internal LocoNetState(LocoBuffer lb)
 {
     this.lb = lb;
     lb.PreviewMessage += ProcessMessage;
     StartIdleDetection();
 }
 /// <summary>
 /// Execute this request.
 /// </summary>
 internal void Execute(Control ui, LocoBuffer lb)
 {
     try
     {
         request(lb);
         OnCompleted(ui, null);
     }
     catch (Exception ex)
     {
         OnCompleted(ui, ex);
     }
 }
        /// <summary>
        /// Go into programming mode.
        /// </summary>
        internal void EnterProgrammingMode(LocoBuffer lb)
        {
            if (!programmingMode)
            {
                // Turn all bits off
                SetB4(lb, false);
                SetB3(lb, false);
                SetB2(lb, false);
                SetB1(lb, false);
                Thread.Sleep(1000);

                // Turn bit 1 on
                SetB1(lb, true);
                Thread.Sleep(6);
                // Turn bit 2 on
                SetB2(lb, true);
                Thread.Sleep(6);
                // Turn bit 3 on
                SetB3(lb, true);
                Thread.Sleep(6);
                // Turn bit 4 on
                SetB4(lb, true);
                Thread.Sleep(6);
                // Turn bit 1 off
                SetB1(lb, false);
                Thread.Sleep(6);
                // Turn bit 2 off
                SetB2(lb, false);
                Thread.Sleep(6);
                // Turn bit 3 off
                SetB3(lb, false);
                Thread.Sleep(6);
                // Turn bit 4 off
                SetB4(lb, false);
                Thread.Sleep(6);

                programmingMode = true;
            }
        }
Beispiel #24
0
 /// <summary>
 /// Default ctor
 /// </summary>
 internal HandlerRegistration(LocoBuffer lb, MessageHandler handler)
 {
     this.lb      = lb;
     this.handler = handler;
 }
Beispiel #25
0
        /// <summary>
        /// Pass the given locobuffer on to all components.
        /// </summary>
        internal void Setup(LocoBuffer lb, LocoNetConfiguration configuration)
        {
            // Allow for null arguments
            lb = lb ?? ConfiguredLocoBuffer;
            configuration = configuration ?? Configuration;

            if ((ConfiguredLocoBuffer != lb) || (Configuration != configuration))
            {
                CloseLocoBuffer();
                locoNet = new LocoNet(lb, configuration);
                asyncLb = new AsyncLocoBuffer(ui, lb);

                lb.SendMessage += LbForwardSendMessage;
                lb.PreviewMessage += LbForwardPreviewMessage;

                var lnState = locoNet.State;
                lnState.StateChanged += LnStateStateChanged;
                lnState.LocoIOQuery += LnStateLocoIoQuery;
                lnState.LocoIOFound += LnStateLocoIoFound;
                lnState.Idle += LnStateIdle;

                LocoNetChanged.Fire(this);
            }
        }
        /// <summary>
        /// Set the duration from left to right
        /// </summary>
        internal void ExitProgrammingMode(LocoBuffer lb)
        {
            if (programmingMode)
            {
                SendNibble(lb, 0x07); // Command
                programmingMode = false;

                // Reset all 4 bits
                SetB4(lb, false);
                SetB3(lb, false);
                SetB2(lb, false);
                SetB1(lb, false);
            }
        }
Beispiel #27
0
 public override void Execute(LocoBuffer lb)
 {
     lb.Send(this, 0x82, 0);
 }
 /// <summary>
 /// Create and start a new processor
 /// </summary>
 public ReceiveProcessor(LocoBuffer lb)
 {
     this.lb = lb;
     this.thread = new Thread(OnRun);
     this.thread.Start();
 }
        /// <summary>
        /// Set the direction of the relays. 
        /// </summary>
        /// <param name="leftLsb">If true, left is the LSB and right is MSB, otherwise left is MSB and right is LSB</param>
        internal void SetRelaisPosition(LocoBuffer lb, bool leftLsb)
        {
            EnterProgrammingMode(lb);

            SendNibble(lb, 0x04); // Command
            SendNibble(lb, leftLsb ? 0 : 1);
        }
        /// <summary>
        /// Read all settings
        /// </summary>
        internal void ReadAll(LocoBuffer lb, LocoNetAddress address)
        {
            // Create a set of all SV's that are relevant
            /*var configs = LocoIOConfig.GetAllSVs();

            // Create the programmer
            var programmer = new Programmer(lb, address);

            // Read all SV's
            programmer.Read(configs);

            // Get all properly read configs
            var validConfigs = configs.Where(x => x.Valid).ToArray();
            */
        }
        /// <summary>
        /// Set the right edge position in degrees
        /// </summary>
        /// <param name="value">Maximum right position (in time units) from 1 - 100</param>
        internal void SetRightDegrees(LocoBuffer lb, int value)
        {
            EnterProgrammingMode(lb);

            SendNibble(lb, 0x03); // Command
            SendNibble(lb, (value >> 1) & 0x07); // value bit 4,3,2
            SendNibble(lb, (value >> 4) & 0x07); // value bit 7,6,5
        }