using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using M2M_RTU_NET;

namespace RTU_CS_demo
{
    public partial class Form1 : Form
    {
        uint stationN;

        public Form1()
        {
            InitializeComponent();
        }

        private string GetModbus_Module_Name(byte[] bSrc, int n)
        {
            string name = System.Text.Encoding.Default.GetString(bSrc, n * 24, 24);
            name = name.Trim('\0');
            return name;
        }

        private string getAPIVersion()
        {
            uint ver, verMain, verSub;
            ver = M2M_RTU.GetDllVersion();
            verMain = (ver & 0xFF00) >> 8;
            verSub = (ver & 0xFF);
            string ver_string = verMain.ToString("X") + verSub.ToString("X02");

            byte[] bVerDate = new byte[32];
            M2M_RTU.GetDllDate(bVerDate);
            ver_string = "V" + ver_string + " " + System.Text.Encoding.Default.GetString(bVerDate).Trim('\0');
            return ver_string;
        }

        private void btn_start_Click(object sender, EventArgs e)
        {
            int res;

            //-- get version
            txtVersion.Text = getAPIVersion();

            //-- (1) get station number
            res = M2M_RTU.GET_Total_Station_NUM(ref stationN);
            if (res == 0)
            {
                txtStationN.Text = stationN.ToString();
                txtStatus.Text = "Initial Success";
            }
            else
                txtStatus.Text = "Initial Fails" + ", Error: " + res.ToString();

            //-- step 2, get station information (can be skip)
            M2M_RTU.OPC_Total_Info staInfo = new M2M_RTU.OPC_Total_Info();
            
            txtInformation.AppendText("========\n");
            for (uint i=0; i<stationN; i++)
            {
                res = M2M_RTU.GET_StationID_Total_Info(i, ref staInfo);
                if(res==0)
                {
                    txtInformation.AppendText("----\n");
                    txtInformation.AppendText("Station ID = " + staInfo.uiStationID.ToString() + "\n");
                    //module type: 0=G-4500, 1=GT-540
                    txtInformation.AppendText("  device type = " + staInfo.uiModule.ToString() + "\n");
                    string moduleName = System.Text.Encoding.Unicode.GetString(staInfo.bModule_Name).Trim('\0');
                    txtInformation.AppendText("  Module Name = " + moduleName + "\n");
                    txtInformation.AppendText("  Modbus Number = " + staInfo.uiModbus_Num.ToString() + "\n");
                    for (int j=0; j<staInfo.uiModbus_Num; j++)
                    {
                        txtInformation.AppendText("\t-- Modbus(" + j.ToString() + ") --" + "\n");
                        string Modbus_name = GetModbus_Module_Name(staInfo.bModbus_Module_Name, j);
                        txtInformation.AppendText("\tName = " + Modbus_name + "\n");
                        txtInformation.AppendText("\tsID = " + staInfo.bSlave_ID[j].ToString() + "\n");
                        txtInformation.AppendText("\tDI x" + staInfo.bDI_Num[j].ToString() + "\n");
                        txtInformation.AppendText("\tDO x" + staInfo.bDO_Num[j].ToString() + "\n");
                        txtInformation.AppendText("\tAI x" + staInfo.bAI_Num[j].ToString() + "\n");
                        txtInformation.AppendText("\tAO x" + staInfo.bAO_Num[j].ToString() + "\n");
                        txtInformation.AppendText("\tCount x" + staInfo.bCounter_Num[j].ToString() + "\n");
                        txtInformation.AppendText("\tenGPS = " + staInfo.usEnGPS[j].ToString() + "\n");
                        txtInformation.AppendText("\n");

                    }
                }else//although return disconnection error, API still return Station Information
                {
                    txtInformation.AppendText("----\n");
                    txtInformation.AppendText("!!!! cannot get Staintion Information !!!!, Error: " + res.ToString() + "\n");
                    //- 沒連線，仍要讀資料
                    txtInformation.AppendText("  device type = " + staInfo.uiModule.ToString() + "\n");
                    string moduleName = System.Text.Encoding.Unicode.GetString(staInfo.bModule_Name).Trim('\0');
                    txtInformation.AppendText("  Module Name = " + moduleName + "\n");
                    txtInformation.AppendText("  Modbus Number = " + staInfo.uiModbus_Num.ToString() + "\n");
                    for (int j = 0; j < staInfo.uiModbus_Num; j++)
                    {
                        txtInformation.AppendText("\t-- Modbus(" + j.ToString() + ") --" + "\n");
                        string Modbus_name = GetModbus_Module_Name(staInfo.bModbus_Module_Name, j);
                        txtInformation.AppendText("\tName = " + Modbus_name + "\n");
                        txtInformation.AppendText("\tsID = " + staInfo.bSlave_ID[j].ToString() + "\n");
                        txtInformation.AppendText("\tDI x" + staInfo.bDI_Num[j].ToString() + "\n");
                        txtInformation.AppendText("\tDO x" + staInfo.bDO_Num[j].ToString() + "\n");
                        txtInformation.AppendText("\tAI x" + staInfo.bAI_Num[j].ToString() + "\n");
                        txtInformation.AppendText("\tAO x" + staInfo.bAO_Num[j].ToString() + "\n");
                        txtInformation.AppendText("\tCount x" + staInfo.bCounter_Num[j].ToString() + "\n");
                        txtInformation.AppendText("\tenGPS = " + staInfo.usEnGPS[j].ToString() + "\n");
                        txtInformation.AppendText("\n");
                    }
                }
                Application.DoEvents();
            }
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            txtInformation.Text = "";
        }

        private void btnRead_Click(object sender, EventArgs e)
        {
            //-- get local data
            uint SID = Convert.ToUInt32(txtStationID.Text);
            byte mbSID = 255;
            ulong value = 0;
            byte bValue = 0;
            uint iValue = 0;
            ushort usValue = 0;
            string strValue;
            //Local IO only. Please don't modify this string, or you will get wrong data
            string mbName = "Local IO";
            byte[] bMbName = System.Text.Encoding.Default.GetBytes(mbName);
            int result;
            int YY=0, Mon=0, DD=0, hh=0, mm=0, ss=0;

            txtIOData.AppendText("----------\n");
            M2M_RTU.GET_DateTime(SID, ref YY, ref Mon, ref DD, ref hh, ref mm, ref ss);
            txtIOData.AppendText("---" + YY.ToString() + "/" + Mon.ToString() + "/" + DD.ToString() + " "
                                        + hh.ToString() + ":" + mm.ToString() + ":" + ss.ToString() + "\n");
            txtIOData.AppendText("Station ID:" + SID.ToString() + ", mbSlave ID:" + mbSID.ToString() + ", Modbus Name=" + mbName + "\n");

            // although, you will get a Error code, but function still return the last value
            //- DI, single channel
            result = M2M_RTU.GET_Modbus_DI_Channel(SID, bMbName, mbSID, 0, ref bValue);
            if (result == 0)
                txtIOData.AppendText("DI ch0 =" + bValue.ToString() + "\n");
            else
                txtIOData.AppendText("DI ch0 =" + bValue.ToString() + ", Error=" + result.ToString()+ "\n");
            
            //- DIs
            result = M2M_RTU.GET_Modbus_DI(SID, bMbName, mbSID, ref value);
            strValue = Convert.ToString(Convert.ToInt32(value), 2);
            if (result == 0)
                txtIOData.AppendText("DIs =" + strValue + "\n");
            else
                txtIOData.AppendText("DIs =" + strValue + " ,Error = " + result.ToString() + "\n");
            
            //- DO, single channel
            result = M2M_RTU.GET_Modbus_DO_Channel(SID, bMbName, mbSID, 0, ref bValue);
            if (result == 0)
                txtIOData.AppendText("DO ch0 =" + bValue.ToString() + "\n");
            else
                txtIOData.AppendText("DO ch0 =" + bValue.ToString() + ", Error=" + result.ToString() + "\n");
            
            //- DOs
            result = M2M_RTU.GET_Modbus_DO(SID, bMbName, mbSID, ref value);
            strValue = Convert.ToString(Convert.ToInt32(value), 2);
            if (result == 0)
                txtIOData.AppendText("DOs =" + strValue + "\n");
            else
                txtIOData.AppendText("DOs =" + strValue + " ,Error = " + result.ToString() + "\n");
            
            //- counter, single channel
            result = M2M_RTU.GET_Modbus_Counter_Channel(SID, bMbName, mbSID, 0, ref iValue);
            if (result == 0)
                txtIOData.AppendText("Counter ch0 =" + value.ToString() + "\n");
            else
                txtIOData.AppendText("Counter ch0 =" + value.ToString() + ", Error=" + result.ToString() + "\n");

            //- don't care these two variable, just pass two variable to the function
            byte bDataFormat = 0;
            byte bType = 0;
            //- AI
            result = M2M_RTU.GET_Modbus_AI_Channel(SID, bMbName, mbSID, 0,
                                ref bDataFormat, ref bType, ref usValue);
            if (result == 0)
            {
                txtIOData.AppendText("AI ch0 Hex :" + usValue.ToString() + "\n");
                double AI_value = usValue / 4095.0 * 20.0;//for GT-540, AI is 12 bits, 0~20mA
                txtIOData.AppendText("  Hex --> mA :" + AI_value.ToString("F3") + " mA" + "\n");
            }
            else
                txtIOData.AppendText("AI ch0 Hex =" + usValue.ToString() + ", Error=" + result.ToString() + "\n");

            //- AO
            result = M2M_RTU.GET_Modbus_AO_Channel(SID, bMbName, mbSID, 0,
                                ref bDataFormat, ref bType, ref usValue);
            if (result == 0)
                txtIOData.AppendText("AO ch0 :" + usValue.ToString() + "\n");
            else
                txtIOData.AppendText("AO ch0 =" + usValue.ToString() + ", Error=" + result.ToString() + "\n");

            byte[] bGPS = new byte[256];
            result = M2M_RTU.GET_Modbus_GPS(SID, bMbName, mbSID, bGPS);
            if (result == 0)
            {
                string GPS_String = System.Text.Encoding.Default.GetString(bGPS).Trim('\0');
                txtIOData.AppendText("GPS :\n" + GPS_String + "\n");
            }
            else
                txtIOData.AppendText("GPS :Error = " + result.ToString() + "\n");

            txtIOData.AppendText("----------\n");

        }

        private void btnWriteDo_Click(object sender, EventArgs e)
        {
            uint SID = Convert.ToUInt32(txtStationID.Text);
            byte mbSID = 255;
            byte bValue = 0;
            byte[] bMbName = System.Text.Encoding.Default.GetBytes("Local IO");
            int result;

            M2M_RTU.GET_Modbus_DO_Channel(SID, bMbName, mbSID, 0, ref bValue);
            if (bValue == 0)
                bValue = 1;
            else
                bValue = 0;

            result = M2M_RTU.WRITE_Modbus_DO_Channel(SID, bMbName, mbSID, 0, bValue);

            if (result == 0)
                MessageBox.Show("success to write DO as " + bValue.ToString() + "\nthe DO status will change later, because GPRS is slow...");
            else
                MessageBox.Show("fails to write DO");

        }

        private void btnWriteAO_Click(object sender, EventArgs e)
        {
            uint SID = Convert.ToUInt32(txtStationID.Text);
            byte mbSID = 255;
            ushort usValue = 0;
            byte[] bMbName = System.Text.Encoding.Default.GetBytes("Local IO");
            byte bDataFormat = 0;
            byte bType = 0;
            int result;

            //- read AO
            result = M2M_RTU.GET_Modbus_AO_Channel(SID, bMbName, mbSID, 0,
                                ref bDataFormat, ref bType, ref usValue);

            if (usValue == 0)
                usValue = 1;
            else
                usValue = 0;

            result = M2M_RTU.WRITE_Modbus_AO_Channel(SID, bMbName, mbSID, 0, usValue);

            if (result == 0)
                MessageBox.Show("success to write AO_0 as " + usValue.ToString() + "\nthe AO status will change later, because GPRS is slow...");
            else
                MessageBox.Show("fails to write AO_0");

        }

        private void btnReadRemote_Click(object sender, EventArgs e)
        {
            //-- get data
            uint SID = Convert.ToUInt32(txtStationID.Text);
            byte mbSID = Convert.ToByte(txtMbID.Text);//--> depend on your modbus slave ID
            string mbName = txtMbName.Text;//-->depend on your module name (on RTU Center)
            byte[] bMbName = System.Text.Encoding.Default.GetBytes(mbName);
            ulong value = 0;
            byte bValue = 0;
            uint iValue = 0;
            ushort usValue = 0;
            string strValue;
            int result;
            int YY=0, Mon=0, DD=0, hh=0, mm=0, ss=0;

            txtRemoteIOData.AppendText("----------\n");
            M2M_RTU.GET_DateTime(SID, ref YY, ref Mon, ref DD, ref hh, ref mm, ref ss);
            txtRemoteIOData.AppendText("---" + YY.ToString() + "/" + Mon.ToString() + "/" + DD.ToString() + " "
                                        + hh.ToString() + ":" + mm.ToString() + ":" + ss.ToString() + "\n");
            txtRemoteIOData.AppendText("Station ID:" + SID.ToString() + ", mbSlave ID:" + mbSID.ToString() + ", Modbus Name=" + mbName + "\n");

            // although, you will get a Error code, but function still return the last value
            //- DI, single channel
            result = M2M_RTU.GET_Modbus_DI_Channel(SID, bMbName, mbSID, 0, ref bValue);
            if (result == 0)
                txtRemoteIOData.AppendText("DI ch0 =" + bValue.ToString() + "\n");
            else
                txtRemoteIOData.AppendText("DI ch0 =" + bValue.ToString() + ", Error=" + result.ToString() + "\n");

            //- DIs
            result = M2M_RTU.GET_Modbus_DI(SID, bMbName, mbSID, ref value);
            strValue = Convert.ToString(Convert.ToInt32(value), 2);
            if (result == 0)
                txtRemoteIOData.AppendText("DIs =" + strValue + "\n");
            else
                txtRemoteIOData.AppendText("DIs =" + strValue + " ,Error = " + result.ToString() + "\n");

            //- DO, single channel
            result = M2M_RTU.GET_Modbus_DO_Channel(SID, bMbName, mbSID, 0, ref bValue);
            if (result == 0)
                txtRemoteIOData.AppendText("DO ch0 =" + bValue.ToString() + "\n");
            else
                txtRemoteIOData.AppendText("DO ch0 =" + bValue.ToString() + ", Error=" + result.ToString() + "\n");

            //- DOs
            result = M2M_RTU.GET_Modbus_DO(SID, bMbName, mbSID, ref value);
            strValue = Convert.ToString(Convert.ToInt32(value), 2);
            if (result == 0)
                txtRemoteIOData.AppendText("DOs =" + strValue + "\n");
            else
                txtRemoteIOData.AppendText("DOs =" + strValue + " ,Error = " + result.ToString() + "\n");

            //- counter, single channel
            result = M2M_RTU.GET_Modbus_Counter_Channel(SID, bMbName, mbSID, 0, ref iValue);
            if (result == 0)
                txtRemoteIOData.AppendText("Counter ch0 =" + value.ToString() + "\n");
            else
                txtRemoteIOData.AppendText("Counter ch0 =" + value.ToString() + ", Error=" + result.ToString() + "\n");

            //- don't care these two variable, just pass two variable to the function
            byte bDataFormat = 0;
            byte bType = 0;
            //- AI
            result = M2M_RTU.GET_Modbus_AI_Channel(SID, bMbName, mbSID, 0,
                                ref bDataFormat, ref bType, ref usValue);
            if (result == 0)
            {
                txtRemoteIOData.AppendText("AI ch0 Hex :" + usValue.ToString() + "\n");
                double AI_value = usValue / 4095.0 * 20.0;//for GT-540, AI is 12 bits, 0~20mA
                txtRemoteIOData.AppendText("  Hex --> mA :" + AI_value.ToString("F3") + " mA" + "\n");
            }
            else
                txtRemoteIOData.AppendText("AI ch0 Hex =" + usValue.ToString() + ", Error=" + result.ToString() + "\n");

            //- AO
            result = M2M_RTU.GET_Modbus_AO_Channel(SID, bMbName, mbSID, 0,
                                ref bDataFormat, ref bType, ref usValue);
            if (result == 0)
                txtRemoteIOData.AppendText("AO ch0 :" + usValue.ToString() + "\n");
            else
                txtRemoteIOData.AppendText("AO ch0 =" + usValue.ToString() + ", Error=" + result.ToString() + "\n");

            txtRemoteIOData.AppendText("----------\n");

        }

        private void btnWriteDoRemote_Click(object sender, EventArgs e)
        {
            uint SID = Convert.ToUInt32(txtStationID.Text);
            byte mbSID = Convert.ToByte(txtMbID.Text);//--> depend on your modbus slave ID            byte bValue = 0;
            string mbName = txtMbName.Text;//-->depend on your module name (on RTU Center)
            byte[] bMbName = System.Text.Encoding.Default.GetBytes(mbName);
            byte bValue = 0;
            int result;

            M2M_RTU.GET_Modbus_DO_Channel(SID, bMbName, mbSID, 0, ref bValue);
            if (bValue == 0)
                bValue = 1;
            else
                bValue = 0;

            result = M2M_RTU.WRITE_Modbus_DO_Channel(SID, bMbName, mbSID, 0, bValue);

            if (result == 0)
                MessageBox.Show("success to write DO as " + bValue.ToString() + "\nthe DO status will change later, because GPRS is slow...");
            else
                MessageBox.Show("fails to write DO");

        }

        private void btnWriteDosRemote_Click(object sender, EventArgs e)
        {
            uint SID = Convert.ToUInt32(txtStationID.Text);
            byte mbSID = Convert.ToByte(txtMbID.Text);//--> depend on your modbus slave ID            byte bValue = 0;
            string mbName = txtMbName.Text;//-->depend on your module name (on RTU Center)
            byte[] bMbName = System.Text.Encoding.Default.GetBytes(mbName);
            ulong value = 0;
            int result;

            M2M_RTU.GET_Modbus_DO(SID, bMbName, mbSID, ref value);
            value++;

            result = M2M_RTU.WRITE_Modbus_DO(SID, bMbName, mbSID, value);

            if (result == 0)
                MessageBox.Show("success to write DO as " + value.ToString() + "\nthe DO status will change later, because GPRS is slow...");
            else
                MessageBox.Show("fails to write DO");
        }

        private void btnWriteAoRemote_Click(object sender, EventArgs e)
        {
            uint SID = Convert.ToUInt32(txtStationID.Text);
            byte mbSID = Convert.ToByte(txtMbID.Text);//--> depend on your modbus slave ID            byte bValue = 0;
            string mbName = txtMbName.Text;//-->depend on your module name (on RTU Center)
            byte[] bMbName = System.Text.Encoding.Default.GetBytes(mbName);
            ushort usValue = 0;
            byte bDataFormat = 0;
            byte bType = 0;
            int result;

            //- read AO
            result = M2M_RTU.GET_Modbus_AO_Channel(SID, bMbName, mbSID, 0,
                                ref bDataFormat, ref bType, ref usValue);
            usValue++;

            result = M2M_RTU.WRITE_Modbus_AO_Channel(SID, bMbName, mbSID, 0, usValue);

            if (result == 0)
                MessageBox.Show("success to write AO_0 as " + usValue.ToString() + "\nthe AO status will change later, because GPRS is slow...");
            else
                MessageBox.Show("fails to write AO_0");

        }

        private void btnWriteCounterRemote_Click(object sender, EventArgs e)
        {
            uint SID = Convert.ToUInt32(txtStationID.Text);
            byte mbSID = Convert.ToByte(txtMbID.Text);//--> depend on your modbus slave ID            byte bValue = 0;
            string mbName = txtMbName.Text;//-->depend on your module name (on RTU Center)
            byte[] bMbName = System.Text.Encoding.Default.GetBytes(mbName);
            int result;

            result = M2M_RTU.WRITE_Modbus_CountZero_Channel(SID, bMbName, mbSID, 0);

            if (result == 0)
                MessageBox.Show("success to write Counter_0 as 0\n change later, because GPRS is slow...");
            else
                MessageBox.Show("fails to write Counter_0");

        }


        private void btnWDT_Click(object sender, EventArgs e)
        {
            int wdt = M2M_RTU.Get_RTUWDT();
            txtInformation.AppendText("----\n");
            txtInformation.AppendText("Soft WDT Value = " + wdt.ToString() + "\n");
            txtInformation.AppendText("----\n");

        }

        private void btnRunRTU_Click(object sender, EventArgs e)
        {
            M2M_RTU.RTU_WakeUpAP(0);
        }

        private void btnCloseRTU_Click(object sender, EventArgs e)
        {
            M2M_RTU.RTU_CloseAP();
        }


    }
}