/// <summary> /// Handle the given message /// </summary> /// <returns>True if handled</returns> protected virtual bool LocoAddress(LocoAddressRequest msg) { log.Trace("Received: LocoAddress: address={0}", msg.Address); var slot = slotTable.FindByAddress(msg.Address, true); if (slot == null) { // No slots available log.Trace("Send: LongAck: no slots available", msg.Address); var result = new LongAck(LocoAddressRequest.Opcode, 0); result.Execute(lb); return(true); } // Normal response SendSlotDataResponse(slot, slot.SlotNumber); return(true); }
/// <summary> /// Initiate the standard address selection procedure to get/create a slot for the given loc. /// </summary> public Slot RequestSlot(ILocState loc) { var slot = Slots.FindByLoc(loc); if (slot != null) { // Slot already available return(slot); } var address = loc.Entity.Address.Value; log.Trace("Requesting slot for {0}", address); var req = new LocoAddressRequest(address); try { req.ExecuteAndWaitForResponse <SlotDataResponse>( LocoBuffer, x => (x.Address == address), RequestSlotTimeout); } catch (TimeoutException) { // No proper response log.Trace("Timeout on slot request for {0}", address); return(null); } var result = Slots.FindByAddress(address, false); if (result == null) { log.Error("Requesting slot succeeded, but no slot found for {0}", address); } else { log.Trace("Requested slot for {0}, using slot {1}", address, result.SlotNumber); } return(result); }
/// <summary> /// Initiate the standard address selection procedure to get/create a slot for the given loc. /// </summary> protected Slot RequestSlot(ILocState loc) { var address = loc.Address.ValueAsInt; log.Trace("RequestSlot(addr={0})", address); lock (transactionLock) { var slot = locSlotMap[loc]; if ((slot != null) && (slot.IsUpdate2Date)) { // Slot already available return(slot); } if (slot != null) { // Slot may be out of date log.Trace("Updating slot {0} for {1}", slot.SlotNumber, address); try { var msg = new SlotDataRequest(slot.SlotNumber); var response = msg.ExecuteAndWaitForResponse <SlotDataResponse>( LocoBuffer, x => (x.Address == address), RequestSlotTimeout); if (response != null) { log.Trace("Updated slot {0} for {1}", slot.SlotNumber, address); slot.Touch(); return(slot); } log.Trace("Updating slot {0} for {1} failed. Slot is different.", slot.SlotNumber, address); locSlotMap.Remove(slot); } catch (TimeoutException ex) { // Ignore for now, just claim a new slot locSlotMap.Remove(slot); } } log.Trace("Requesting slot for {0}", address); var req = new LocoAddressRequest(address); try { // Perform the loco-address request var response = req.ExecuteAndWaitForResponse <SlotDataResponse>( LocoBuffer, x => (x.Address == address), RequestSlotTimeout); if (response == null) { log.Trace("Requesting slot for {0} failed: Timeout", address); throw new TimeoutException(); } // We now got a valid slot data response slot = new Slot(response); log.Trace("Requesting slot for {0} succeeded: got slot {1}", address, slot.SlotNumber); // Get status var usageStatus = response.Status1 & SlotStatus1.BusyActiveMask; if ((usageStatus == SlotStatus1.InUse) || (response.Status1.IsSet(SlotStatus1.ConsistUp))) { // We're not allowed to use this slot log.Trace("Slot status does not allow to use the slot: {0}", response.Status1); return(null); } // We can use the slot, perform a NULL move to set it in use. log.Trace("Request NULL move for slot {0}, address {1}", slot.SlotNumber, address); var msg = new MoveSlotsRequest(slot.SlotNumber, slot.SlotNumber); var moveResponse = msg.ExecuteAndWaitForResponse <SlotDataResponse>( LocoBuffer, x => (x.Address == address), RequestSlotTimeout); if (moveResponse == null) { log.Trace("NULL move for slot {0}, address {1} failed: timeout", slot.SlotNumber, address); return(null); } // We can now use the slot log.Trace("Request NULL move for slot {0}, address {1} succeeded", slot.SlotNumber, address); locSlotMap[loc] = slot; // Set decoder type var status = UpdateDecoderType(response.Status1, loc); log.Trace("Write slot {0} stat1 {1} for address {2}", slot.SlotNumber, status, address); var slotStat1Msg = new SlotStat1Request(response.Slot, status); slotStat1Msg.Execute(lb); return(slot); } catch (TimeoutException) { // No proper response log.Trace("Timeout on slot request for {0}", address); return(null); } } }
/// <summary> /// Loc address request /// </summary> public override bool Visit(LocoAddressRequest msg, Master data) { return(data.LocoAddress(msg)); }
public virtual TReturn Visit(LocoAddressRequest msg, TData data) { return(default(TReturn)); }