debugging events

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • guyarkam@gmail.com

    debugging events

    I have the following code in which I use events to read on eth or
    serial port when data commes in. The ASCHFProtLib library is a third
    party library that I have to use as it is. Unfortunately this version
    of my code does not work. It seems that the events are not triggering
    when there is a data on any of the eth or serial ports. Basicaly all
    the events handler functions (OnMsgRecv and similar) are not executed.
    I have included a piece of code that was provided by the library
    author. In this code I noticed that the events handlers where defined
    as private static void. However, modifying my code to reflect this,
    could not solve the problem. I am not very familliar with C#
    Any help will be appreciated.
    Thanks Guy

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // THE CODE BELOW DOES NOT WORK
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    using System;
    using System.Collecti ons.Generic;
    using System.Componen tModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows. Forms;
    using ASCHFProtLib;

    namespace IDTrak
    {
    public partial class IDTrak : Form
    {
    private static string _IPAdd;
    private static int _Port;
    private HFProt m_ASCProt;
    private static string _SerialPort;
    private static int _BaudRate = 38400;
    private string stCommand;
    private int iNumberOfTags;
    private int iTagsDisplayloo pCounter;
    private string stUid;
    private static bool boolConnectedEt h = false;
    private static bool boolConnectedSe rial = false;
    private static string stCommand_Inven toryAnntenna_1 = "M01";
    // Inventory
    private static string stCommand_SetPo llingOn =
    "P08701";// =Polling mode is ON
    private static string stCommand_SetBa udRate = "P001";
    // default is 0xC0=19200
    private static string stCommand_SetPo llingOff =
    "P08700";// =Polling mode is OFF
    private static string stCommand_SetMa xScanRepeat = "P081";
    //P08205 (default is 0x06)
    private static string stCommand_SetMa xScanFail = "P082";
    //P08205 (default is 0x05)
    private static string stCommand_SetTi meSlots = "P02A";
    //P02A10 =16 Times Slots
    private static string stCommand_ReadW ithQuietMode =
    "P08001";// =read with quiet mode
    private static string stCommand_ReadW ithoutQuietMode =
    "P08000";// (default)
    private static string stCommand_SetRf PowerLevel = "P0D2";
    //0x00 to 0x28 default is 0x14 =4watts
    private static string stCommand_Switc hRfPowerOn =
    "P09001";//0x00 default
    private static string stCommand_Switc hRfPowerOff =
    "P09000";//
    private static string stCommand_Reque stReaderParamet ers = "F0";
    private static string stCommand_GetRe aderVersion = "V0";
    // Reader Version
    // bool exit = false;
    // int index;
    // string rstr;
    public IDTrak()
    {
    try
    {
    InitializeCompo nent();
    _IPAdd = this.tBIpAddres s.GetPureIPAddr ess();
    _Port = Convert.ToInt32 (this.tBPort.Te xt.ToString());
    this.cBSerialPo rt.SelectedInde x = 0;
    iTagsDisplayloo pCounter = 0;
    this.cBSerialPo rt.SelectedInde x = 0;
    // this.gBEth.Enab led = false;
    // Modifcations for GPI Version of the software.
    //this.cbBReaderS elect.SelectedI ndex = 0;
    this.lReader.En abled = false;
    this.cbBReaderS elect.Enabled = false;
    this.gBCommands .Enabled = false;
    // this.lParam.Ena bled = false;
    //this.cBParam.En abled = false;
    this.toolStripS tatusLabel1.Tex t = "Not connected";
    m_ASCProt = new ASCHFProtLib.HF Prot();
    InitializeEthIn terface();
    this.tbOutput.A ppendText("Eth interface initialized
    \r\n");
    InitializeRS232 Interface();
    this.tbOutput.A ppendText("RS23 2 interface initialized
    \r\n");
    }
    catch
    {
    MessageBox.Show ("Error in interface initialization" ,
    "IDTrak", MessageBoxButto ns.OKCancel, MessageBoxIcon. Asterisk);
    }
    }
    private bool InitReaderRs232 ()
    { // This has to be modified
    bool result = true;
    /*
    this.tbOutput.A ppendText("Init ializing the reader" +
    "\r\n");
    stCommand = "H0"; // Heartbeat
    result = m_ASCProt.SendR S232(stCommand) ;
    stCommand = "V0"; // Version
    result = m_ASCProt.SendR S232(stCommand) ;
    stCommand = "P0FF01"; // Set anything
    result = m_ASCProt.SendR S232(stCommand) ;
    */
    return result;
    }
    private void InitializeEthIn terface() {
    m_ASCProt.OnEth Connect += new
    ASCHFProtLib.HF Prot.EthConnect (OnConnect);
    m_ASCProt.OnEth AscMsg += new
    ASCHFProtLib.HF Prot.MsgEthRece ived(OnMsgEthRe cv);
    // m_ASCProt.OnEth AscMsg += new
    ASCHFProtLib.HF Prot.MsgEthRece ived(processMes sage);

    }
    private void InitializeRS232 Interface()
    {
    this.m_ASCProt. OnRS232AscMsg += new
    ASCHFProtLib.HF Prot.MsgRS232Re ceived(OnMsgRec v);
    this.m_ASCProt. OnRS232MsgErr += new
    ASCHFProtLib.HF Prot.RS232MsgEr ror(OnRS232MsgE rr);

    }

    private void OnRS232MsgErr(o bject sender, int err)
    {
    this.tbOutput.A ppendText("Erro r Received on Serial Port: "
    + _SerialPort + " " + err.ToString() + "\r\n");
    }

    private void CloseRS232Inter face()
    {
    m_ASCProt.Close RSCom();
    m_ASCProt.OnRS2 32AscMsg -= new
    ASCHFProtLib.HF Prot.MsgRS232Re ceived(OnMsgRec v);
    m_ASCProt = null;
    }

    private void CloseEthInterfa ce()
    {
    m_ASCProt.Close Socket();
    m_ASCProt.OnEth Connect -= new
    ASCHFProtLib.HF Prot.EthConnect (OnConnect);
    m_ASCProt.OnEth AscMsg -= new
    ASCHFProtLib.HF Prot.MsgEthRece ived(OnMsgEthRe cv);
    m_ASCProt = null;
    }
    /*
    private void OnMsgRecv(objec t sender, string msg)
    {

    this.tbOutput.A ppendText("Rece ived on Serial Port: " +
    _SerialPort + " " + msg + "\r\n");
    }

    */

    private static void OnMsgRecv(objec t sender, string msg) {
    MessageBox.Show ("This is a message", "IDTrak",
    MessageBoxButto ns.OKCancel, MessageBoxIcon. Asterisk);


    }
    private void OnConnect(objec t sender, bool connect)
    {
    if (connect)
    {
    this.tbOutput.A ppendText("IPAd d:" + _IPAdd + " Port: "
    + _Port.ToString( ) + " connected!" + "\r\n");
    }
    else {
    this.tbOutput.A ppendText("IPAd d:" + _IPAdd + " Port: "
    + _Port.ToString( ) + "Disconnect ed!" + "\r\n");
    }
    }


    //private void processMessage( string msg)
    private void processMessage( object sender, string msg)
    {

    int index = msg.IndexOf("m" );
    int iTotnumberOfTag s;
    if (index == 0){
    //8F
    this.iNumberOfT ags = Convert.ToInt32 (msg.Substring( 3,
    2),16);

    if (this.iNumberOf Tags != 143)
    {
    this.listView1. Items.Clear();
    iTotnumberOfTag s = this.iNumberOfT ags;
    this.tbOutput.A ppendText("Tota l Number of tags: " +
    iNumberOfTags.T oString() + "\r\n");
    this.listView1. BeginUpdate();
    for (int i = 0; i < iTotnumberOfTag s; i++)
    {
    stUid = msg.Substring(5 + (i * 16), 16);
    ListViewItem listItem = new
    ListViewItem((i +1).ToString()) ;
    listItem.SubIte ms.Add(stUid);
    this.listView1. Items.Add(listI tem);
    }

    //Call EndUpdate when you finish adding items to
    the ListView.
    this.listView1. EndUpdate();

    iTotnumberOfTag s = 0;
    }
    else {// the List contains 15 UID and more are still to
    come

    this.listView1. BeginUpdate();
    for (int i = 0; i < 15; i++)
    {
    stUid = msg.Substring(5 + (i * 16), 16);
    ListViewItem listItem = new ListViewItem((i +
    this.iTagsDispl ayloopCounter). ToString());
    listItem.SubIte ms.Add(stUid);
    this.listView1. Items.Add(listI tem);
    }
    this.listView1. EndUpdate();
    this.iTagsDispl ayloopCounter += 15;
    //Carefull!! This will not work if the inventory
    was sent on another antenna
    stCommand = stCommand_Inven toryAnntenna_1;
    m_ASCProt.SendS ocket(stCommand ); // send the
    command again to retrieve
    // the remaining
    UIDs
    }
    }
    else {
    this.tbOutput.A ppendText("Some thing bad" +
    iNumberOfTags.T oString() + "\r\n");
    }


    }
    private void OnMsgEthRecv(ob ject sender, string msg)
    {

    // processMessage( msg);
    this.tbOutput.A ppendText("Recv Eth: " + msg + "\r\n");

    }
    private void label1_Click(ob ject sender, EventArgs e)
    {

    }

    private void tBIpAddress_Tex tChanged(object sender, EventArgs
    e)
    {

    }

    private void toolStripStatus Label1_Click(ob ject sender,
    EventArgs e)
    {

    }

    private void listView1_Selec tedIndexChanged (object sender,
    EventArgs e)
    {

    }

    private void btConnectDiscon nectEth_Click(o bject sender,
    EventArgs e)
    {


    if (!boolConnected Eth) // Not yet connected: Connect
    {

    this.tbOutput.A ppendText("Open Eth: " + "Connecting ..."
    + "\r\n");
    if (!m_ASCProt.Ope nSocket(_IPAdd, _Port))// unable to
    connect
    {
    this.toolStripS tatusLabel1.Tex t = "Not connected";
    boolConnectedEt h = false;
    this.gBCommands .Enabled = false;
    }
    else // successfull connection
    {

    this.toolStripS tatusLabel1.Tex t = "Connected" ;
    this.btConDisco nnectEth.Text = "Disconnect ";
    this.gBCommands .Enabled = true;
    boolConnectedEt h = true;

    this.tBIpAddres s.Enabled = false;
    this.lIpAddress .Enabled = false;
    this.gBRS232.En abled = false;
    this.tBPort.Ena bled = false;
    this.lPort.Enab led = false;
    }
    }
    else // already connected: Disconnect
    {

    boolConnectedEt h = false;
    m_ASCProt.Close Socket();
    // m_ASCProt.Close RSCom();
    this.toolStripS tatusLabel1.Tex t = "Disconnect ed";
    this.gBCommands .Enabled = false;
    this.gBRS232.En abled = true;
    this.btConDisco nnectEth.Text = "Connect";
    this.lIpAddress .Enabled = true;
    this.lPort.Enab led = true;
    this.tBIpAddres s.Enabled = true;
    this.tBPort.Ena bled = true;
    }

    }

    private void IDTrak_Load(obj ect sender, EventArgs e)
    {

    }

    private void IDTrak_FormClos ed(object sender,
    FormClosedEvent Args e)
    {

    }

    private void IDTrak_FormClos ing(object sender,
    FormClosingEven tArgs e)
    {
    try
    {
    //CloseEthInterfa ce();
    if (boolConnectedE th)
    {

    CloseEthInterfa ce();
    }
    else if (boolConnectedS erial)
    {
    CloseRS232Inter face();
    }
    else
    {
    this.tbOutput.A ppendText("Erro r!!: No communication
    interface to close \r\n");
    }

    }
    catch
    { }
    }

    private void btReader_Click( object sender, EventArgs e)
    {

    }

    private void tBCommand_Mouse Hover(object sender, EventArgs e)
    {
    // The tool tips should be displayed
    }

    private void bSend_Click(obj ect sender, EventArgs e)
    {
    int selectedIndex = this.cBCommand. SelectedIndex;
    this.listView1. Items.Clear();
    iTagsDisplayloo pCounter = 0;
    //this.listView1. Items[i].SubItems.Add(s tUid);
    //Add a switch statement here to select the command
    //Convert.ToInt32 (this.tBPort.Te xt.ToString());
    if (selectedIndex >= 0) // List item selected: do nothing
    since
    { //stCommand is already set properly

    }
    else // No list item selected: The user migh have entered a
    new command
    {
    stCommand = this.cBCommand. Text.ToString() +
    cBParam.Text.To String();
    }
    this.tbOutput.A ppendText("Comm and to send " + stCommand + "
    \r\n");

    if (boolConnectedE th)
    {

    m_ASCProt.SendS ocket(stCommand );
    }
    else if (boolConnectedS erial)
    {
    m_ASCProt.SendR S232(stCommand) ;
    }
    else
    {
    this.tbOutput.A ppendText("Erro r!! No communication
    interface ready \r\n");
    }

    }

    private void tBCommand_TextC hanged(object sender, EventArgs e)
    {

    }

    private void tBCommand_KeyPr ess(object sender,
    KeyPressEventAr gs e)
    {
    // if (e.Equals(Keys. Return)) {
    // stCommand = this.tBCommand. Text.ToString() ;
    // m_ASCProt.SendS ocket(stCommand );
    // }
    }

    private void btConnectDiscon nectRS232_Click (object sender,
    EventArgs e)
    {

    if (!boolConnected Serial)
    {// Not yet connected: Connect
    this.tbOutput.A ppendText("Open Com: " + _SerialPort + "
    Connecting..." + "\r\n");
    if (!m_ASCProt.Ope nRSCom(_BaudRat e, _SerialPort)) //
    unable to connect
    {
    this.gBCommands .Enabled = false;
    this.tbOutput.A ppendText("Conn ecting to " +
    _SerialPort + " @ " + _BaudRate + " Baud failled \r\n");
    this.toolStripS tatusLabel1.Tex t = "Not connected";
    }
    else // successfull connection
    {
    this.tbOutput.C lear();
    this.tbOutput.A ppendText("Seri al Port " +
    _SerialPort + " @ " + _BaudRate + "Baud is up and OK.\r\nNow
    initializing the reader... \r\n");
    if (!InitReaderRs2 32())
    {
    this.tbOutput.A ppendText("Read er Initialization
    failled" + "\r\n");
    }
    else {
    this.tbOutput.A ppendText("Read er Initialization
    is Ok" + "\r\n");
    boolConnectedSe rial = true;
    this.toolStripS tatusLabel1.Tex t = "Connected" ;
    this.gBCommands .Enabled = true;
    this.gBEth.Enab led = false;
    this.lSerialPor t.Enabled = false;
    this.cBSerialPo rt.Enabled = false;
    this.btConDisco nnectRS232.Text = "Disconnect ";

    }


    }
    }
    else
    { // already connected: Disconnect


    boolConnectedSe rial = false;
    //m_ASCProt.Close Socket();
    m_ASCProt.Close RSCom();
    this.toolStripS tatusLabel1.Tex t = "Disconnect ed";
    this.gBCommands .Enabled = false;
    this.gBEth.Enab led = true;
    this.btConDisco nnectRS232.Text = "Connect";
    this.lSerialPor t.Enabled = true;
    this.cBSerialPo rt.Enabled = true;
    }

    }

    private void toolTip1_Popup( object sender, PopupEventArgs e)
    {

    }

    private void cbBReaderSelect _SelectedIndexC hanged(object
    sender, EventArgs e)
    {

    }

    private void cBCommand_Selec tedIndexChanged (object sender,
    EventArgs e)
    {
    int selectedIndex = this.cBCommand. SelectedIndex;

    switch (selectedIndex) {
    case 0:
    stCommand = stCommand_Inven toryAnntenna_1;
    this.lParam.Ena bled = false;
    this.cBParam.En abled = false;
    break;
    case 1:
    stCommand = stCommand_SetPo llingOn;
    this.lParam.Ena bled = false;
    this.cBParam.En abled = false;
    break;
    case 2:
    stCommand = stCommand_SetPo llingOff;
    this.lParam.Ena bled = false;
    this.cBParam.En abled = false;
    break;
    case 3:
    this.cBParam.Se lectedIndex = 3;
    stCommand = stCommand_SetMa xScanFail +
    this.cBParam.Se lectedItem.ToSt ring();
    this.lParam.Ena bled = true;
    this.cBParam.En abled = true;
    break;
    case 4:
    this.cBParam.Se lectedIndex = 4;
    stCommand = stCommand_SetTi meSlots +
    this.cBParam.Se lectedItem.ToSt ring();
    this.lParam.Ena bled = true;
    this.cBParam.En abled = true;
    break;
    case 5:
    stCommand = stCommand_ReadW ithQuietMode;
    this.lParam.Ena bled = false;
    this.cBParam.En abled = false;
    break;
    case 6:
    stCommand = stCommand_ReadW ithoutQuietMode ;
    this.lParam.Ena bled = false;
    this.cBParam.En abled = false;
    break;

    case 7:
    this.cBParam.Se lectedIndex = 7; //P08106 (default
    is 0x06)
    stCommand = stCommand_SetMa xScanRepeat +
    this.cBParam.Se lectedItem.ToSt ring();
    this.lParam.Ena bled = true;
    this.cBParam.En abled = true;
    break;
    case 8:
    this.cBParam.Se lectedIndex = 8; // default is
    0xC0=19200
    stCommand = stCommand_SetBa udRate +
    this.cBParam.Se lectedItem.ToSt ring();
    this.lParam.Ena bled = true;
    this.cBParam.En abled = true;
    break;
    case 9:
    this.cBParam.Se lectedIndex = 9; //0x00 to 0x28
    default is 0x14 =4watts
    stCommand = stCommand_SetRf PowerLevel +
    this.cBParam.Se lectedItem.ToSt ring();
    this.lParam.Ena bled = true;
    this.cBParam.En abled = true;
    break;

    case 10:
    stCommand = stCommand_Switc hRfPowerOn; //P09001
    default
    this.lParam.Ena bled = false;
    this.cBParam.En abled = false;
    break;
    case 11:
    stCommand = stCommand_Switc hRfPowerOff; //P09000
    this.lParam.Ena bled = false;
    this.cBParam.En abled = false;
    break;
    case 12:
    this.cBParam.Se lectedIndex = 12;
    stCommand = stCommand_Reque stReaderParamet ers +
    this.cBParam.Se lectedItem.ToSt ring();
    this.lParam.Ena bled = true;
    this.cBParam.En abled = true;
    break;
    case 13:
    stCommand = stCommand_GetRe aderVersion;
    this.lParam.Ena bled = false;
    this.cBParam.En abled = false;
    break;
    default:
    // stCommand ;
    this.lParam.Ena bled = false;
    this.cBParam.En abled = false;
    break;



    }

    }

    private void cBSerialPort_Se lectedIndexChan ged(object sender,
    EventArgs e)
    {
    _SerialPort = this.cBSerialPo rt.SelectedItem .ToString();
    }
    }
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // END OF THE CODE THAT DOES NOT WORK
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // THE CODE BELOW DOES WORK!!!!
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    using System;
    using ASCHFProtLib;
    namespace TestConApp_ASCH FDll
    {
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    class Class1
    {
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static string _IPAdd;
    static int _Port;
    static string _Comport;
    [STAThread]
    static void Main(string[] args)
    {
    //
    // TODO: Add code to start application here
    //
    bool exit = false;
    int index;
    string rstr;
    HFProt m_ASCProt;
    try
    {
    _Comport = string.Empty;
    Console.WriteLi ne("Console Test Application using
    ASCHFProtLib.dl l");
    Console.WriteLi ne("10.11.2005\ n");
    Console.WriteLi ne("Type Exit to close!!!\n\n");
    m_ASCProt = new ASCHFProtLib.HF Prot();
    m_ASCProt.OnRS2 32AscMsg += new
    ASCHFProtLib.HF Prot.MsgRS232Re ceived(OnMsgRec v);
    m_ASCProt.OnEth Connect += new
    ASCHFProtLib.HF Prot.EthConnect (OnConnect);
    m_ASCProt.OnEth AscMsg += new
    ASCHFProtLib.HF Prot.MsgEthRece ived(OnMsgEthRe cv);
    Console.WriteLi ne("Enter 'Open COM1' to open COM Port
    1.");
    Console.WriteLi ne("Enter 'Open IP:192.168.100. 101
    Port:3001' to open Ethernet Port.");
    Console.WriteLi ne("Enter 'Close COM' to close COM
    Port.");
    Console.WriteLi ne("Enter 'Close Eth' to close Eth
    Port.");
    while (!exit)
    {
    rstr = Console.ReadLin e().ToUpper();


    if (rstr.IndexOf(" EXIT") == 0)
    exit = true;
    else if (rstr.IndexOf(" OPEN") == 0)
    {
    index = rstr.IndexOf("C OM");
    if (index 0)
    {
    _Comport = rstr.Substring( index);
    if (m_ASCProt.Open RSCom(19200, _Comport))
    {
    Console.WriteLi ne(_Comport + " : 19200
    Boud connected!");
    }
    else
    Console.WriteLi ne(_Comport + " could
    not be opened!");
    }
    else
    {
    index = rstr.IndexOf("I P:");
    if (index 0)
    {
    _IPAdd = rstr.Substring( index + 3,
    rstr.IndexOf(' ', index + 3) - (index + 3));
    _Port =
    Convert.ToInt32 (rstr.Substring (rstr.IndexOf(" PORT:") +
    "PORT:".Length) );
    if (!m_ASCProt.Ope nSocket(_IPAdd,
    _Port))
    Console.WriteLi ne("Error openning
    port!\n");
    }
    else
    Console.WriteLi ne("Wrong
    command!!!\n");
    }
    }
    else if (rstr.IndexOf(" CLOSE") == 0)
    {
    if (rstr.IndexOf(" COM") 0)
    {
    m_ASCProt.Close RSCom();
    Console.WriteLi ne(_Comport + " closed!");
    }
    else if (rstr.IndexOf(" ETH") 0)
    {
    m_ASCProt.Close Socket();
    }
    else
    Console.WriteLi ne("Wrong command!!!\n");
    }
    else
    {
    if (m_ASCProt.Send RS232(rstr))
    {
    Console.WriteLi ne("SendCom: " + rstr);
    if (m_ASCProt.Send Socket(rstr))
    Console.WriteLi ne("SendEth: " + rstr);
    }
    else if (m_ASCProt.Send Socket(rstr))
    Console.WriteLi ne("SendEth: " + rstr);
    else
    Console.WriteLi ne("Not send!");
    }
    }

    m_ASCProt.Close RSCom();
    Console.WriteLi ne(_Comport + " closed!");
    m_ASCProt.Close Socket();
    m_ASCProt.OnRS2 32AscMsg -= new
    ASCHFProtLib.HF Prot.MsgRS232Re ceived(OnMsgRec v);
    m_ASCProt.OnEth Connect -= new
    ASCHFProtLib.HF Prot.EthConnect (OnConnect);
    m_ASCProt.OnEth AscMsg -= new
    ASCHFProtLib.HF Prot.MsgEthRece ived(OnMsgEthRe cv);
    m_ASCProt = null; Console.WriteLi ne("RETURN!");
    Console.Read();
    }
    catch
    { }
    }
    private static void OnMsgRecv(objec t sender, string msg)
    {
    Console.WriteLi ne("RecvCom: " + msg + "\n");
    }
    private static void OnConnect(objec t sender, bool connect)
    {
    if (connect)
    Console.WriteLi ne("IPAdd:" + _IPAdd + " Port: " +
    _Port.ToString( ) + " connected!");
    else
    Console.WriteLi ne("IPAdd:" + _IPAdd + " Port: " +
    _Port.ToString( ) + " disconnected!") ;
    }
    private static void OnMsgEthRecv(ob ject sender, string msg)
    {
    Console.WriteLi ne("RecvEth: " + msg + "\n");
    }
    }
    }


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // END OF THE CODE THAT DOES WORK
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Working...