static void Main()
    {
        BandiCropModule BCM = new BandiCropModule();

        //ConnectEyesen ce = new ConnectEyesen();
        //DevInfo dev = new DevInfo();

        // TEST CONNECTION
        //ce.ConnectToServer("192.168.1.222", 7777);
        //Console.WriteLine(ce.RecieveMassage());

        // RUN TEST
        //BCM.run_module_test();

        // LOAD CROP DATA
        MWStructArray crops_db = BCM.load_crop_db();

        // TEST DONG OBJECT TO APPLY CONTROLS
        DongConfig nare_testbed = new DongConfig(1);

        nare_testbed.name            = "NARE_TESTBED";
        nare_testbed.fan_total       = 5;
        nare_testbed.ch_exhaust_fans = new int[4] {
            1, 2, 3, 4
        };
        nare_testbed.ch_ceiling_vents_L1 = new int[1] {
            1
        };
        nare_testbed.ch_side_vents_L1 = new int[1] {
            2
        };
        nare_testbed.ch_heater = new int[1] {
            3
        };


        // SPECIFY DONG STATE AND CROP
        string    crop_name  = "TOMATO";
        DongState dong_state = new DongState();

        dong_state.temp_in    = 4;
        dong_state.temp_out   = -3;
        dong_state.hum_in     = 50;
        dong_state.hum_out    = 40;
        dong_state.hum_bed    = 30;
        dong_state.co2_supply = true;
        dong_state.rain       = true;

        // CHECK CROP STATUS
        MWStructArray env_status = BCM.crop_env_checker(crops_db, crop_name, dong_state);

        // CHECK FOR REQUIRED CONTROL ACTIONS
        MWStructArray control_actions = BCM.crop_env_controller(crops_db, crop_name, dong_state);

        // APPLY CONTROL TO NARE_TESTBED
        BCM.autoswitch_control(control_actions, nare_testbed);

        Console.WriteLine("\nPress any key to exit.");
        Console.ReadKey();
    }
    // DO CONTROL ACTION BASED ON ENVIRONMENT CHECKING OUTPUT
    public MWStructArray crop_env_controller(MWStructArray crops_db, string crop, DongState sensors)

    {
        Console.WriteLine("\n======================= CROP CONTROLLER OUTPUT =======================");
        BandiCropAnalyzer.CropAnalyzer crop_controller = new BandiCropAnalyzer.CropAnalyzer();

        // Initialize checkers
        String[]      checker_names = { "vpd_check", "dewpoint_check", "crop_temp_check" };
        MWStructArray checker_list  = new MWStructArray(1, 1, checker_names);

        // Initialize optional inputs (by pair): verbose, TRUE/FALSE, vpd_min, vpd_min_val, vpd_max, vpd_max_val, dewtemp_offset, dewtemp_offset_val
        //MWCharArray vpd = "vpd", dewpoint = "dewpoint";
        MWCharArray    checkers = "checkers", verbose = "verbose", crop_name = "crop_name", crop_name_select = "";
        MWCharArray    rh_bed = "rh_bed", co2_supply = "co2_supply", rain = "rain";
        MWCharArray    vpd_min = "vpd_min", vpd_max = "vpd_max", dewtemp_offset = "dewtemp_offset";
        MWLogicalArray TRUE = new MWLogicalArray(true), FALSE = new MWLogicalArray(false);
        MWNumericArray vpd_min_val = 0.5, vpd_max_val = 1.2, dewtemp_offset_val = 1.0;

        // initialize output struct fields - FOR REFERENCE
        String[] vpd_check_fields       = { "type", "code", "state", "vpd", "vpd_min", "vpd_max", "hum_adj", "adjust_unit" };
        String[] dewpoint_check_fields  = { "type", "code", "state", "temp", "temp_dew", "dewtemp_offset", "adjust", "adjust_unit" };
        String[] crop_temp_check_fields = { "type", "code", "state", "temp", "temp_min", "temp_max", "adjust", "adjust_unit" };

        // Set checker options
        checker_list.SetField("vpd_check", TRUE);
        checker_list.SetField("dewpoint_check", TRUE);
        checker_list.SetField("crop_temp_check", TRUE);

        // Create struct for output
        MWStructArray control_action = new MWStructArray();

        try
        {
            // Full usage: crop.env_check(crops, temp_c_in, rh_in, crop_name, crop_name_select, checkers, checker_list, vpd_min, vpd_min_val, vpd_max, vpd_max_val, verbose, FALSE);
            crop_name_select = crop;
            MWNumericArray temp_c_in  = sensors.temp_in;    // deg Celsius
            MWNumericArray rh_in      = sensors.hum_in;     // %
            MWNumericArray temp_c_out = sensors.temp_out;   // deg Celsius
            MWNumericArray rh_out     = sensors.hum_out;    // %
            MWNumericArray hum_bed    = sensors.hum_bed;    // %
            MWLogicalArray co2_state  = sensors.co2_supply; // %
            MWLogicalArray rain_state = sensors.rain;       // %

            return(control_action = (MWStructArray)crop_controller.env_controller(crops_db, crop_name_select,
                                                                                  temp_c_in, rh_in, temp_c_out, rh_out,
                                                                                  rh_bed, hum_bed,
                                                                                  co2_supply, co2_state,
                                                                                  rain, rain_state));
        }
        catch
        {
            throw;
        }
    }
    // IMPLEMENTING THE ENVIRONMENT CHECK ROUTINES
    public MWStructArray crop_env_checker(MWStructArray crops_db, string crop, DongState sensors)
    {
        //Console.WriteLine("\n======================= ENVIRONMENT ANALYSIS =======================");

        BandiCropAnalyzer.CropAnalyzer crop_analyzer = new BandiCropAnalyzer.CropAnalyzer();

        // Initialize checkers
        String[]      checker_names = { "vpd_check", "dewpoint_check", "crop_temp_check" };
        MWStructArray checker_list  = new MWStructArray(1, 1, checker_names);

        // Initialize optional inputs (by pair): verbose, TRUE/FALSE, vpd_min, vpd_min_val, vpd_max, vpd_max_val, dewtemp_offset, dewtemp_offset_val
        //MWCharArray vpd = "vpd", dewpoint = "dewpoint";
        MWCharArray    checkers = "checkers", verbose = "verbose", crop_name = "crop_name", crop_name_select = "";
        MWCharArray    vpd_min = "vpd_min", vpd_max = "vpd_max", dewtemp_offset = "dewtemp_offset";
        MWLogicalArray TRUE = new MWLogicalArray(true), FALSE = new MWLogicalArray(false);
        MWNumericArray vpd_min_val = 0.5, vpd_max_val = 1.2, dewtemp_offset_val = 1.0;

        // initialize output struct fields - FOR REFERENCE
        String[] vpd_check_fields       = { "type", "code", "state", "vpd", "vpd_min", "vpd_max", "hum_adj", "adjust_unit" };
        String[] dewpoint_check_fields  = { "type", "code", "state", "temp", "temp_dew", "dewtemp_offset", "adjust", "adjust_unit" };
        String[] crop_temp_check_fields = { "type", "code", "state", "temp", "temp_min", "temp_max", "adjust", "adjust_unit" };

        // Set checker options
        checker_list.SetField("vpd_check", TRUE);
        checker_list.SetField("dewpoint_check", TRUE);
        checker_list.SetField("crop_temp_check", TRUE);

        // Create struct for output
        MWStructArray  result      = new MWStructArray();
        MWNumericArray result_code = null;

        try
        {
            // Full usage: crop.env_check(crops, temp_c_in, rh_in, crop_name, crop_name_select, checkers, checker_list, vpd_min, vpd_min_val, vpd_max, vpd_max_val, verbose, FALSE);
            crop_name_select = crop;
            MWNumericArray temp_c_in = sensors.temp_in; // deg Celsius
            MWNumericArray rh_in     = sensors.hum_in;  // %

            result      = (MWStructArray)crop_analyzer.env_check(crops_db, temp_c_in, rh_in, crop_name, crop_name_select, checkers, checker_list);
            result_code = (MWNumericArray)result.GetField("code");

            Console.WriteLine("RESULT CODE: " + result_code);
            //Console.WriteLine("Press any key to exit.");
            //Console.ReadKey();

            return(result);
        }
        catch
        {
            throw;
        }
    }
    public void run_module_test()
    {
        BandiCropAnalyzer.CropAnalyzer crop_analyzer = new BandiCropAnalyzer.CropAnalyzer();

        // TEST CROP AND SENSOR FEED
        string    crop_name  = "STRAWBERRY";
        DongState dong_state = new DongState();

        dong_state.temp_in    = 4;
        dong_state.temp_out   = -3;
        dong_state.hum_in     = 50;
        dong_state.hum_out    = 40;
        dong_state.hum_bed    = 30;
        dong_state.co2_supply = true;
        dong_state.rain       = true;

        // TEST DONG OBJECT TO APPLY CONTROLS
        DongConfig dong = new DongConfig(1)
        {
            name      = "NARE_DONG",
            fan_total = 5,
        };

        MWStructArray crops_db = load_crop_db();

        // DO CROP ENVIRONMENT CHECK ONLY
        MWStructArray env_status = crop_env_checker(crops_db, crop_name, dong_state);

        // PARSE CHECK RESULTS FOR DISPLAY
        int    print_level = 2; // 0->1->2 : INCREASING VERBOSITY
        string result_out  = parse_results(env_status, print_level);

        // PERFORM STATUS CHECK + CONTROL ACTION
        MWStructArray control_actions = crop_env_controller(crops_db, crop_name, dong_state);

        // APPLY CONTROL TO DONG1
        autoswitch_control(control_actions, dong);

        Console.WriteLine("\nMODULE TEST COMPLETE. PRESS ANY KEY TO CONTINUE...");
        Console.ReadKey();
    }