/// <summary> /// </summary> /// <param name="flags"> /// </param> /// <param name="type"> /// </param> /// <param name="id"> /// </param> /// <param name="name"> /// </param> public ChannelBase(ChannelFlags flags, ChannelType type, uint id, string name = "") { this.channelFlags = flags; this.channelType = type; this.ChannelId = id; this.ChannelName = name; }
void JoinedChannel(object sender, ServerChatEventArgs e) { chat.AddChat(new ChatNode("Joined Channel: ", CssClasses.JoiningChannel), new ChatNode(e.Text, CssClasses.ChannelName)); ChannelFlags flags = (ChannelFlags)e.Flags; if ((flags & ChannelFlags.SilentChannel) == ChannelFlags.SilentChannel) { chat.AddChat(new ChatNode("This is a silent channel.", CssClasses.SilentChannel)); } ThreadStart ts = delegate { this.Text = string.Format(CultureInfo.CurrentCulture, "Chat Channel: {0}", e.Text); this.TabText = this.Text; }; if (InvokeRequired) { BeginInvoke(ts); } else { ts(); } }
internal AmqpModelContainer(IModel channel, ChannelFlags flags, AmqpChannelPooler source) { Channel = channel; Flags = flags; Source = source; Created = Environment.TickCount; }
private void _read() { _flags = new MacFlags(m_io, this, m_root); _aMpduId = m_io.ReadU4le(); _numDelimiters = m_io.ReadU1(); _mcs = m_io.ReadU1(); _numStreams = m_io.ReadU1(); _rssiCombined = m_io.ReadU1(); _rssiAntCtl = new List <byte>(); for (var i = 0; i < 4; i++) { _rssiAntCtl.Add(m_io.ReadU1()); } _rssiAntExt = new List <byte>(); for (var i = 0; i < 4; i++) { _rssiAntExt.Add(m_io.ReadU1()); } _extChannelFreq = m_io.ReadU2le(); _extChannelFlags = new ChannelFlags(m_io, this, m_root); _rfSignalNoise = new List <SignalNoise>(); for (var i = 0; i < 4; i++) { _rfSignalNoise.Add(new SignalNoise(m_io, this, m_root)); } _evm = new List <uint>(); for (var i = 0; i < 4; i++) { _evm.Add(m_io.ReadU4le()); } }
internal ChannelUpdatePacket(BigInteger channelID, ChannelFlags flags, string tag) : base(Packet.Type.CHANNEL_UPDATE) { this.AddData(channelID); this.AddData(NetConvert.HostToNetworkOrder((uint)flags)); this.AddData(tag); }
/// <summary> /// creates a new <see cref="ChatChannelKey"/> /// </summary> /// <param name="service">name of service</param> /// <param name="name">name of channel</param> /// <param name="included">flags channel has to include</param> /// <param name="excluded">flags channel mustn't include</param> public ChatChannelKey(string service, string name, ChannelFlags included = ChannelFlags.None, ChannelFlags excluded = ChannelFlags.None) { Service = service; Name = name; Included = included; Excluded = excluded; }
public Channel(BigInteger id, String name, ChannelType type, ChannelFlags flags, string tag) { this._id = id; this._name = name; this._type = type; this._flags = flags; this._tag = tag; }
public ChannelEntry(ushort networkId, ushort serviceId, string region, string name, ChannelFlags flags) { this.NetworkId = networkId; this.ServiceId = serviceId; this.Region = region; this.Name = name; this.Flags = flags; }
/// <summary> /// Creates a new <see cref="DataCell"/> from serialization parameters. /// </summary> /// <param name="info">The <see cref="SerializationInfo"/> with populated with data.</param> /// <param name="context">The source <see cref="StreamingContext"/> for this deserialization.</param> protected DataCell(SerializationInfo info, StreamingContext context) : base(info, context) { // Deserialize data cell m_channelFlags = (ChannelFlags)info.GetValue("channelFlags", typeof(ChannelFlags)); m_reservedFlags = (ReservedFlags)info.GetValue("reservedFlags", typeof(ReservedFlags)); m_sampleNumber = info.GetUInt16("sampleNumber"); }
public Channel(string name, ChannelFlags flags) { _Name = name; _Flags = flags; _Users = new List<User>(); _BannedIPs = new List<string>(); _BannedUsers = new List<string>(); }
public Channel(int id, string name, ChannelFlags flags, string password) { this.ID = id; this.Name = name; this.Flags = flags; this.Password = password; if (password != "") this.Flags |= ChannelFlags.Passworded; }
public Channel(string name, ChannelFlags flags, bool closeable, User owner) { _Name = name; _Flags = flags; _Closeable = closeable; if (closeable) Owner = owner; _Users = new List<User>(); _BannedIPs = new List<string>(); _BannedUsers = new List<string>(); }
public Channel(int id, string name, ChannelFlags flags, string password) { this.ID = id; this.Name = name; this.Flags = flags; this.Password = password; if (password != "") { this.Flags |= ChannelFlags.Passworded; } }
/// <summary> /// constructor for channel mute events /// </summary> /// <param name="id">5-byte channel id</param> /// <param name="name">channel name</param> /// <param name="mute">whether the channel is muted or not</param> /// <param name="channelType">channel type</param> public ChannelStatusEventArgs(BigInteger id, String name, ChannelFlags flags, byte channelType, string tag) { this.ID = id; this.Name = name; this.Flags = flags; this.TypeID = channelType; if (Enum.IsDefined(typeof(ChannelType), (int)channelType)) { this.Type = (ChannelType)channelType; } this.Tag = tag; }
void HandleChannelList(PacketReader reader) { byte type = reader.ReadByte(); string name = reader.ReadCString(); ChannelFlags flags = (ChannelFlags)reader.ReadByte(); UInt32 size = reader.ReadUInt32(); for (UInt32 i = 0; i < size; i++) { reader.ReadUInt64(); reader.ReadByte(); } }
internal AmqpModelContainer GetModel(ChannelFlags flags) { #if !DISABLE_CHANNELPOOLING if(flags == ChannelFlags.Consumer) { //Do not pool consumer related channels return CreateModel(flags); } //Search pool for a model: AmqpModelContainer model = null; //First get the queue ConcurrentQueue<AmqpModelContainer> queue = _pool[(int)flags]; bool retry; int tick = Environment.TickCount; //Dequeue queue until an unexpired model is found do { retry = false; model = null; if (queue.TryDequeue(out model)) { if (HasModelExpired(tick, model)) { DestroyModel(model); // dispose model for good retry = true; } } } while (retry ); if (model == null) { //Wasn't found, so create a new one model = CreateModel(flags); } return model; #else return CreateModel(flags); #endif }
private AmqpModelContainer CreateModel(ChannelFlags flags) { var model = conn.CreateModel(); if (flags == ChannelFlags.RPC || flags == ChannelFlags.RPCWithPublisherConfirms) { return(new RPCModelContainer(model, flags == ChannelFlags.RPCWithPublisherConfirms, this)); } return(new AmqpModelContainer(model, flags, this) { Discard = flags == ChannelFlags.Consumer }); }
/// <summary> /// </summary> /// <param name="channelType"> /// </param> /// <param name="channelId"> /// </param> /// <param name="channelName"> /// </param> /// <param name="flags"> /// </param> /// <param name="otherData"> /// </param> /// <returns> /// </returns> public static byte[] Create( ChannelType channelType, uint channelId, string channelName, ChannelFlags flags, byte[] otherData) { PacketWriter writer = new PacketWriter(60); writer.WriteByte((byte)channelType); writer.WriteUInt32(channelId); writer.WriteString(channelName); writer.WriteUInt32((UInt32)flags); writer.WriteBytes(otherData); return writer.Finish(); }
public void VirtualChannelOpenEvent(int openHandle, ChannelEvents Event, byte[] data, int dataLength, uint totalLength, ChannelFlags dataFlags) { DataChannelEventArgs args = new DataChannelEventArgs() { Data = data, DataFlags = dataFlags, DataLength = dataLength, Event = Event, OpenHandle = openHandle, TotalLength = totalLength }; OnDataChannelEvent(args); }
public static string [] ChannelFlagsArray(int Value) { string [] values; string value_list; ChannelFlags cf_mask = (ChannelFlags)Value; value_list = cf_mask.ToString("G"); values = value_list.Split(','); for (int i = 0; i < values.Length; i++) { values[i] = values[i].Trim(); } return(values); }
/// <summary> /// </summary> /// <param name="channelType"> /// </param> /// <param name="channelId"> /// </param> /// <param name="channelName"> /// </param> /// <param name="flags"> /// </param> /// <param name="otherData"> /// </param> /// <returns> /// </returns> public static byte[] Create( ChannelType channelType, uint channelId, string channelName, ChannelFlags flags, byte[] otherData) { PacketWriter writer = new PacketWriter(60); writer.WriteByte((byte)channelType); writer.WriteUInt32(channelId); writer.WriteString(channelName); writer.WriteUInt32((UInt32)flags); writer.WriteBytes(otherData); return(writer.Finish()); }
/// <summary> /// </summary> /// <param name="side"> /// </param> /// <param name="flags"> /// </param> /// <param name="type"> /// </param> public RestrictedChannel(Side side, ChannelFlags flags, ChannelType type) : base(flags, type, (uint)side) { switch (side) { case Side.Advisor: this.ChannelName = "Advisor"; this.OnCheckRestriction += this.CheckAdvisorStatus; break; case Side.Clan: this.ChannelName = "Clan"; this.OnCheckRestriction += this.CheckClanStatus; break; case Side.Gm: this.ChannelName = "Suiv's Playground"; this.OnCheckRestriction += this.CheckGmStatus; break; case Side.Guardian: this.ChannelName = "Guardians"; this.OnCheckRestriction += this.CheckGuardianStatus; break; case Side.Mixed: this.ChannelName = "Mixed"; this.OnCheckRestriction += this.CheckMixedRestriction; break; case Side.Monster: this.ChannelName = "Monstaaaar"; this.OnCheckRestriction += this.CheckMonsterRestriction; break; case Side.Neutral: this.ChannelName = "Neutral"; this.OnCheckRestriction += this.CheckNeutralRestriction; break; case Side.Omni: this.ChannelName = "Omni-Tek"; this.OnCheckRestriction += this.CheckOmniRestriction; break; } }
internal AmqpModelContainer GetModel(ChannelFlags flags) { #if ENABLE_CHANNELPOOLING //Search pool for a model: AmqpModelContainer model = null; //First get the queue ConcurrentQueue<AmqpModelContainer> queue; if (_pool.TryGetValue(flags, out queue)) { bool retry; int tick = Environment.TickCount; //Dequeue queue until an unexpired model is found do { retry = false; model = null; if (queue.TryDequeue(out model)) { if (HasModelExpired(tick, model)) { DisposeModel(model); // dispose model retry = true; } } } while (retry ); } if (model == null) { //Wasn't found, so create a new one model = new AmqpModelContainer(conn.CreateModel(), flags, this); } return model; #else return new AmqpModelContainer( conn.CreateModel(), flags, this); #endif }
internal AmqpModelContainer GetModel(ChannelFlags flags) { #if !DISABLE_CHANNELPOOLING if (flags == ChannelFlags.Consumer) { //Do not pool consumer related channels return(CreateModel(flags)); } //Search pool for a model: AmqpModelContainer model = null; //First get the queue ConcurrentQueue <AmqpModelContainer> queue = _pool[(int)flags]; bool retry; int tick = Environment.TickCount; //Dequeue queue until an unexpired model is found do { retry = false; model = null; if (queue.TryDequeue(out model)) { if (HasModelExpired(tick, model)) { DestroyModel(model); // dispose model for good retry = true; } } }while (retry); if (model == null) { //Wasn't found, so create a new one model = CreateModel(flags); } return(model); #else return(CreateModel(flags)); #endif }
void OnMessage(Message message) { // don't process bot messages or messages coming from a channel not flagged for display if (message.Author.Bot || (message.ChannelID != chatchannel && message.ChannelID != rpgchannel)) { return; } DiscordChatChannel channel; if (!channels.TryGetValue(message.ChannelID, out channel)) { ChannelFlags flags = ChannelFlags.Chat | (message.ChannelID == rpgchannel ? ChannelFlags.Game : ChannelFlags.None); channel = new DiscordChatChannel(discord, message.ChannelID, flags); channels[message.ChannelID] = channel; context.GetModule <StreamModule>().AddChannel(channel); } channel.ProcessMessage(message); }
internal AmqpModelContainer GetModel(ChannelFlags flags) { #if ENABLE_CHANNELPOOLING //Search pool for a model: AmqpModelContainer model = null; //First get the queue ConcurrentQueue <AmqpModelContainer> queue; if (_pool.TryGetValue(flags, out queue)) { bool retry; int tick = Environment.TickCount; //Dequeue queue until an unexpired model is found do { retry = false; model = null; if (queue.TryDequeue(out model)) { if (HasModelExpired(tick, model)) { DisposeModel(model); // dispose model retry = true; } } }while (retry); } if (model == null) { //Wasn't found, so create a new one model = new AmqpModelContainer(conn.CreateModel(), flags, this); } return(model); #else return(new AmqpModelContainer(conn.CreateModel(), flags, this)); #endif }
public ChannelFlags GetFlags() { ChannelFlags flags = (ChannelFlags)1; if (this.Password.Length > 0) { flags |= ChannelFlags.Passworded; } if (this.Hidden) { flags |= ChannelFlags.Hidden; } if (this.BlockGlobalChat) { flags |= ChannelFlags.BlockGlobalChat; } if (!this.AnnounceChannelJoinLeave) { flags |= ChannelFlags.BlockJoinLeaveMsg; } return(flags); }
/// <summary> /// </summary> /// <param name="flags"> /// </param> /// <param name="type"> /// </param> /// <param name="id"> /// </param> /// <param name="name"> /// </param> public OrganizationChannel(ChannelFlags flags, ChannelType type, uint id, string name = "") : base(flags, type, id, name) { }
public void VirtualChannelOpenEvent(int openHandle, ChannelEvents Event, IntPtr pData, int dataLength, uint totalLength, ChannelFlags dataFlags) { Debug.Print(DateTime.Now + " " + Environment.MachineName + ": VirtualChannelOpenEvent: " + Event); switch (Event) { case ChannelEvents.DataReceived: var data = new byte[dataLength]; Marshal.Copy(pData, data, 0, dataLength); switch (dataFlags & ChannelFlags.Only) { case ChannelFlags.Only: MessageReceived(ChannelMessage.FromByteArray(data)); break; case ChannelFlags.First: memoryStream = new MemoryStream((int)totalLength); memoryStream.Write(data, 0, data.Length); break; case ChannelFlags.Middle: if (memoryStream != null) { memoryStream.Write(data, 0, data.Length); } break; case ChannelFlags.Last: if (memoryStream != null) { memoryStream.Write(data, 0, data.Length); memoryStream.Position = 0; MessageReceived(ChannelMessage.FromStream(memoryStream)); memoryStream = null; } break; } break; case ChannelEvents.WriteCanceled: case ChannelEvents.WriteComplete: /* * The VirtualChannelWrite function is asynchronous. When the write operation has been completed, * your VirtualChannelOpenEvent function receives a CHANNEL_EVENT_WRITE_COMPLETE notification. * Until that notification is received, the caller must not free or reuse the pData buffer passed to VirtualChannelWrite */ Marshal.FreeHGlobal(pData); break; } }
public Channel(string name, ChannelFlags flags) : this(name, flags, true, null) { }
/// <summary> /// get a channel which matches the filters /// </summary> /// <param name="service">service which manages the channel</param> /// <param name="included">flags channel has to have</param> /// <param name="excluded">flags channel mustn't have</param> /// <returns>access to channel</returns> public IChatChannel GetChannel(string service, ChannelFlags included = ChannelFlags.All, ChannelFlags excluded = ChannelFlags.None) { lock (channellock) return(channels.FirstOrDefault(c => c.Service == service && (c.Flags & included) == included && (c.Flags & excluded) == ChannelFlags.None)); }
private AmqpModelContainer CreateModel(ChannelFlags flags) { var model = conn.CreateModel(); if (flags == ChannelFlags.RPC || flags == ChannelFlags.RPCWithPublisherConfirms) { return new RPCModelContainer(model, flags == ChannelFlags.RPCWithPublisherConfirms, this); } return new AmqpModelContainer(model, flags, this) { Discard = flags == ChannelFlags.Consumer }; }
/// <summary> /// </summary> /// <param name="flags"> /// </param> /// <param name="type"> /// </param> /// <param name="id"> /// </param> /// <param name="name"> /// </param> public GlobalChannel(ChannelFlags flags, ChannelType type, uint id, string name = "") : base(flags | ChannelFlags.CantIgnore | ChannelFlags.NoInternational, type, id, name) { }
/// <summary> /// Returns true if the channel has the specified flags. /// </summary> /// <param name="chan">The channel to check</param> /// <param name="flags">The flags to check for</param> protected bool ChannelHasFlags(Channel chan, ChannelFlags flags) { return (chan.Flags & flags) == flags; }
/// <summary> /// get all channels which are matching the filters /// </summary> /// <param name="included">flags channel has to have</param> /// <param name="excluded">flags channel mustn't have</param> /// <returns>channels which match the specified flags</returns> public IEnumerable <IChatChannel> GetChannels(ChannelFlags included = ChannelFlags.All, ChannelFlags excluded = ChannelFlags.None) { lock (channellock) return(channels.Where(c => (c.Flags & included) == included && (c.Flags & excluded) == ChannelFlags.None)); }
/// <summary> /// creates a new <see cref="DiscordChatChannel"/> /// </summary> /// <param name="discord"></param> /// <param name="key"></param> /// <param name="flags">additional flags for channel (<see cref="ChannelFlags.Bot"/> is automatically set)</param> public DiscordChatChannel(DiscordRest discord, string key, ChannelFlags flags = ChannelFlags.None) { this.discord = discord; this.flags = flags; Key = key; }
/// <summary> /// Parses the binary header image. /// </summary> /// <param name="buffer">Binary image to parse.</param> /// <param name="startIndex">Start index into <paramref name="buffer"/> to begin parsing.</param> /// <param name="length">Length of valid data within <paramref name="buffer"/>.</param> /// <returns>The length of the data that was parsed.</returns> protected override int ParseHeaderImage(byte[] buffer, int startIndex, int length) { DataFrame parentFrame = Parent; DataFrameParsingState frameState = parentFrame.State; IDataCellParsingState state = State; RevisionNumber revision = parentFrame.ConfigurationFrame.RevisionNumber; int x, index = startIndex; byte analogs, digitals, phasors; // Read data buffer if using phasor data file format if (UsePhasorDataFileFormat && frameState.RemainingPdcBlockPmus == 0) { m_dataBuffer = BigEndian.ToUInt32(buffer, index); index += 4; } // Get data cell flags m_channelFlags = (ChannelFlags)buffer[index]; analogs = buffer[index + 1]; index += 2; // Parse PDCstream specific header image if (revision >= RevisionNumber.Revision2 && frameState.RemainingPdcBlockPmus == 0) { // Strip off reserved flags m_reservedFlags = (ReservedFlags)analogs & ~ReservedFlags.AnalogWordsMask; // Leave analog word count analogs &= (byte)ReservedFlags.AnalogWordsMask; } else { // Older revisions didn't allow analogs m_dataRate = analogs; analogs = 0; } if (frameState.RemainingPdcBlockPmus > 0) { // PDC Block PMU's contain exactly 2 phasors, 0 analogs and 1 digital phasors = 2; analogs = 0; digitals = 1; UsingPdcExchangeFormat = true; // Decrement remaining PDC block PMU's frameState.RemainingPdcBlockPmus--; } else { // Parse number of digitals and phasors for normal PMU cells digitals = buffer[index]; phasors = buffer[index + 1]; index += 2; if (revision >= RevisionNumber.Revision2) { // Strip off IEEE flags FormatFlags = (FormatFlags)digitals & ~FormatFlags.DigitalWordsMask; // Leave digital word count digitals &= (byte)FormatFlags.DigitalWordsMask; } // Check for PDC exchange format if (UsingPdcExchangeFormat) { // In cases where we are using PDC exchange the phasor count is the number of PMU's in the PDC block int pdcBlockPmus = phasors - 1; // <-- Current PMU counts as one frameState.RemainingPdcBlockPmus = pdcBlockPmus; frameState.CellCount += pdcBlockPmus; // PDC Block PMU's contain exactly 2 phasors, 0 analogs and 1 digital phasors = 2; analogs = 0; digitals = 1; // Get data cell flags for PDC block PMU m_channelFlags = (ChannelFlags)buffer[index]; UsingPdcExchangeFormat = true; index += 2; } else { // Parse PMU's sample number m_sampleNumber = BigEndian.ToUInt16(buffer, index); index += 2; } } // Algorithm Case: Determine best course of action when stream counts don't match counts defined in the // external INI based configuration file. Think about what *will* happen when new data appears in the // stream that's not in the config file - you could raise an event notifying consumer about the mismatch // instead of raising an exception - could even make a boolean property that would allow either case. // The important thing to consider is that to parse the cell images you have to have a defined // definition (see base class method "DataCellBase.ParseBodyImage"). If you have more items defined // in the stream than you do in the config file then you won't get the new value, too few items and you // don't have enough definitions to correctly interpret the data (that would be bad) - either way the // definitions won't line up with the appropriate data value and you won't know which one is missing or // added. I can't change the protocol so this is enough argument to just raise an error for config // file/stream mismatch. So for now we'll just throw an exception and deal with consequences :) // Note that this only applies to BPA PDCstream protocol because of external configuration. // Addendum: After running this with several protocol implementations I noticed that if a device wasn't // reporting, the phasor count dropped to zero even if there were phasors defined in the configuration // file, so the only time an exception is thrown is if there are more phasors defined in the the stream // than there are defined in the INI file... // At least this number of phasors should be already defined in BPA PDCstream configuration file if (phasors > ConfigurationCell.PhasorDefinitions.Count) throw new InvalidOperationException( "Stream/Config File Mismatch: Phasor value count in stream (" + phasors + ") does not match defined count in configuration file (" + ConfigurationCell.PhasorDefinitions.Count + ") for " + ConfigurationCell.IDLabel); // If analog values get a clear definition in INI file at some point, we can validate the number in the // stream to the number in the config file, in the mean time we dyanmically add analog definitions to // configuration cell as needed (they are only defined in data frame of BPA PDCstream) if (analogs > ConfigurationCell.AnalogDefinitions.Count) { for (x = ConfigurationCell.AnalogDefinitions.Count; x < analogs; x++) { ConfigurationCell.AnalogDefinitions.Add(new AnalogDefinition(ConfigurationCell, "Analog " + (x + 1), 1, 0.0D, AnalogType.SinglePointOnWave)); } } // If digital values get a clear definition in INI file at some point, we can validate the number in the // stream to the number in the config file, in the mean time we dyanmically add digital definitions to // configuration cell as needed (they are only defined in data frame of BPA PDCstream) if (digitals > ConfigurationCell.DigitalDefinitions.Count) { for (x = ConfigurationCell.DigitalDefinitions.Count; x < digitals; x++) { ConfigurationCell.DigitalDefinitions.Add(new DigitalDefinition(ConfigurationCell, "Digital Word " + (x + 1))); } } // Unlike most all other protocols the counts defined for phasors, analogs and digitals in the data frame // may not exactly match what's defined in the configuration frame as these values are defined in an external // INI file for BPA PDCstream. As a result, we manually assign the counts to the parsing state so that these // will be the counts used to parse values from data frame in the base class ParseBodyImage method state.PhasorCount = phasors; state.AnalogCount = analogs; state.DigitalCount = digitals; // Status flags and remaining data elements will parsed by base class in the ParseBodyImage method return (index - startIndex); }
bool HasFlag(ChannelFlags flag) { return(_channelFlags.HasAnyFlag(flag)); }
/// <summary> /// </summary> /// <param name="flags"> /// </param> /// <param name="type"> /// </param> /// <param name="id"> /// </param> /// <param name="name"> /// </param> public RaidChannel(ChannelFlags flags, ChannelType type, uint id, string name = "") : base(flags, type, id, name) { }
/// <summary> /// Parses the binary header image. /// </summary> /// <param name="buffer">Binary image to parse.</param> /// <param name="startIndex">Start index into <paramref name="buffer"/> to begin parsing.</param> /// <param name="length">Length of valid data within <paramref name="buffer"/>.</param> /// <returns>The length of the data that was parsed.</returns> protected override int ParseHeaderImage(byte[] buffer, int startIndex, int length) { DataFrame parentFrame = Parent; DataFrameParsingState frameState = parentFrame.State; IDataCellParsingState state = State; RevisionNumber revision = parentFrame.ConfigurationFrame.RevisionNumber; int x, index = startIndex; byte analogs, digitals, phasors; // Read data buffer if using phasor data file format if (UsePhasorDataFileFormat && frameState.RemainingPdcBlockPmus == 0) { m_dataBuffer = BigEndian.ToUInt32(buffer, index); index += 4; } // Get data cell flags m_channelFlags = (ChannelFlags)buffer[index]; analogs = buffer[index + 1]; index += 2; // Parse PDCstream specific header image if (revision >= RevisionNumber.Revision2 && frameState.RemainingPdcBlockPmus == 0) { // Strip off reserved flags m_reservedFlags = (ReservedFlags)analogs & ~ReservedFlags.AnalogWordsMask; // Leave analog word count analogs &= (byte)ReservedFlags.AnalogWordsMask; } else { // Older revisions didn't allow analogs m_dataRate = analogs; analogs = 0; } if (frameState.RemainingPdcBlockPmus > 0) { // PDC Block PMU's contain exactly 2 phasors, 0 analogs and 1 digital phasors = 2; analogs = 0; digitals = 1; UsingPdcExchangeFormat = true; // Decrement remaining PDC block PMU's frameState.RemainingPdcBlockPmus--; } else { // Parse number of digitals and phasors for normal PMU cells digitals = buffer[index]; phasors = buffer[index + 1]; index += 2; if (revision >= RevisionNumber.Revision2) { // Strip off IEEE flags FormatFlags = (FormatFlags)digitals & ~FormatFlags.DigitalWordsMask; // Leave digital word count digitals &= (byte)FormatFlags.DigitalWordsMask; } // Check for PDC exchange format if (UsingPdcExchangeFormat) { // In cases where we are using PDC exchange the phasor count is the number of PMU's in the PDC block int pdcBlockPmus = phasors - 1; // <-- Current PMU counts as one frameState.RemainingPdcBlockPmus = pdcBlockPmus; frameState.CellCount += pdcBlockPmus; // PDC Block PMU's contain exactly 2 phasors, 0 analogs and 1 digital phasors = 2; analogs = 0; digitals = 1; // Get data cell flags for PDC block PMU m_channelFlags = (ChannelFlags)buffer[index]; UsingPdcExchangeFormat = true; index += 2; } else { // Parse PMU's sample number m_sampleNumber = BigEndian.ToUInt16(buffer, index); index += 2; } } // Algorithm Case: Determine best course of action when stream counts don't match counts defined in the // external INI based configuration file. Think about what *will* happen when new data appears in the // stream that's not in the config file - you could raise an event notifying consumer about the mismatch // instead of raising an exception - could even make a boolean property that would allow either case. // The important thing to consider is that to parse the cell images you have to have a defined // definition (see base class method "DataCellBase.ParseBodyImage"). If you have more items defined // in the stream than you do in the config file then you won't get the new value, too few items and you // don't have enough definitions to correctly interpret the data (that would be bad) - either way the // definitions won't line up with the appropriate data value and you won't know which one is missing or // added. I can't change the protocol so this is enough argument to just raise an error for config // file/stream mismatch. So for now we'll just throw an exception and deal with consequences :) // Note that this only applies to BPA PDCstream protocol because of external configuration. // Addendum: After running this with several protocol implementations I noticed that if a device wasn't // reporting, the phasor count dropped to zero even if there were phasors defined in the configuration // file, so the only time an exception is thrown is if there are more phasors defined in the the stream // than there are defined in the INI file... // At least this number of phasors should be already defined in BPA PDCstream configuration file if (phasors > ConfigurationCell.PhasorDefinitions.Count) { throw new InvalidOperationException( "Stream/Config File Mismatch: Phasor value count in stream (" + phasors + ") does not match defined count in configuration file (" + ConfigurationCell.PhasorDefinitions.Count + ") for " + ConfigurationCell.IDLabel); } // If analog values get a clear definition in INI file at some point, we can validate the number in the // stream to the number in the config file, in the mean time we dyanmically add analog definitions to // configuration cell as needed (they are only defined in data frame of BPA PDCstream) if (analogs > ConfigurationCell.AnalogDefinitions.Count) { for (x = ConfigurationCell.AnalogDefinitions.Count; x < analogs; x++) { ConfigurationCell.AnalogDefinitions.Add(new AnalogDefinition(ConfigurationCell, "Analog " + (x + 1), 1, 0.0D, AnalogType.SinglePointOnWave)); } } // If digital values get a clear definition in INI file at some point, we can validate the number in the // stream to the number in the config file, in the mean time we dyanmically add digital definitions to // configuration cell as needed (they are only defined in data frame of BPA PDCstream) if (digitals > ConfigurationCell.DigitalDefinitions.Count) { for (x = ConfigurationCell.DigitalDefinitions.Count; x < digitals; x++) { ConfigurationCell.DigitalDefinitions.Add(new DigitalDefinition(ConfigurationCell, "Digital Word " + (x + 1))); } } // Unlike most all other protocols the counts defined for phasors, analogs and digitals in the data frame // may not exactly match what's defined in the configuration frame as these values are defined in an external // INI file for BPA PDCstream. As a result, we manually assign the counts to the parsing state so that these // will be the counts used to parse values from data frame in the base class ParseBodyImage method state.PhasorCount = phasors; state.AnalogCount = analogs; state.DigitalCount = digitals; // Status flags and remaining data elements will parsed by base class in the ParseBodyImage method return(index - startIndex); }