public void Prime(ZACommons commons, EventDriver eventDriver)
    {
        var relayBatteries = commons.GetBlockGroupWithName(BATTERY_GROUP);

        if (relayBatteries == null)
        {
            throw new Exception("Missing group: " + BATTERY_GROUP);
        }
        var relaySystems = commons.GetBlockGroupWithName(SYSTEMS_GROUP);

        if (relaySystems == null)
        {
            throw new Exception("Missing group: " + SYSTEMS_GROUP);
        }

        // Wake up batteries
        var batteries = ZACommons.GetBlocksOfType <IMyBatteryBlock>(relayBatteries.Blocks);

        ZACommons.EnableBlocks(batteries, true);
        ZACommons.SetBatteryRecharge(batteries, false);
        // And activate flight systems
        ZACommons.EnableBlocks(relaySystems.Blocks, true);

        eventDriver.Schedule(1.0, Release);
    }
Beispiel #2
0
    private void RechargeOneBattery(List <IMyBatteryBlock> batteries)
    {
        for (var e = batteries.GetEnumerator(); e.MoveNext();)
        {
            var battery = e.Current;

            if (!battery.Enabled || battery.ProductionEnabled /* huh?! */)
            {
                if (!battery.Enabled)
                {
                    battery.GetActionWithName("OnOff_On").Apply(battery);
                }
                ZACommons.SetBatteryRecharge(battery, true);
                return;
            }
        }
    }
Beispiel #3
0
    private void DisableOneBattery(List <IMyBatteryBlock> batteries, PowerDetails totalDetails)
    {
        for (var e = batteries.GetEnumerator(); e.MoveNext();)
        {
            var battery = e.Current;

            if (battery.Enabled && battery.ProductionEnabled)
            {
                // But only if we can actually spare it
                var wouldBeOutput = totalDetails.CurrentPowerOutput - battery.CurrentPowerOutput;
                var wouldBeLoad   = wouldBeOutput / (totalDetails.MaxPowerOutput - battery.MaxPowerOutput);
                if (wouldBeLoad <= POWER_MANAGER_HIGH_LOAD_THRESHOLD)
                {
                    battery.GetActionWithName("OnOff_Off").Apply(battery);
                    ZACommons.SetBatteryRecharge(battery, true);
                }
                return;
            }
        }
    }
Beispiel #4
0
    public void HandleCommand(ZACommons commons, string argument)
    {
        argument = argument.Trim().ToLower();
        if (argument == "forcerecharge")
        {
            var batteries = GetBatteries(commons);

            CurrentState = STATE_DISABLED;
            ZACommons.SetBatteryRecharge(batteries, true);
            return;
        }
        else if (argument == "pause")
        {
            CurrentState = null;
            Active       = false;
        }
        else if (argument == "resume")
        {
            CurrentState = null;
            Active       = true;
        }
    }
Beispiel #5
0
    public void Run(ZACommons commons)
    {
        var batteries = GetBatteries(commons);

        if (CurrentState == null)
        {
            // First time run, get to known state and return
            CurrentState         = STATE_NORMAL;
            SinceLastStateChange = TimeSpan.FromSeconds(0);
            ZACommons.SetBatteryRecharge(batteries, false);
            return;
        }

        SinceLastStateChange += commons.Program.ElapsedTime;

        var    aggregateDetails = new AggregateBatteryDetails(batteries);
        string stateStr         = "Unknown";

        switch (CurrentState)
        {
        case STATE_NORMAL:
            if (SinceLastStateChange >= DischargeInterval)
            {
                // Don't check again until next interval, regardless of whether we
                // change state
                SinceLastStateChange = TimeSpan.FromSeconds(0);

                // Only recharge if there is available power, e.g. the batteries have no load,
                // and there is need to
                if (aggregateDetails.CurrentPowerOutput == 0.0f &&
                    aggregateDetails.CurrentStoredPower < aggregateDetails.MaxStoredPower &&
                    Active)
                {
                    CurrentState = STATE_RECHARGE;
                    ZACommons.SetBatteryRecharge(batteries, true);
                }
                else
                {
                    // Force discharge, just in case
                    ZACommons.SetBatteryRecharge(batteries, false);
                }
            }
            stateStr = Active ? "Normal" : "Paused";
            break;

        case STATE_RECHARGE:
            // Too bad we don't have access to battery input (w/o parsing DetailInfo)
            // Then we could figure out non-battery load and cancel recharge pre-emptively
            // when needed
            if (SinceLastStateChange >= RechargeInterval)
            {
                CurrentState         = STATE_NORMAL;
                SinceLastStateChange = TimeSpan.FromSeconds(0);
                ZACommons.SetBatteryRecharge(batteries, false);
            }
            stateStr = "Recharging";
            break;

        case STATE_DISABLED:
            // Switch back to auto if full
            if (aggregateDetails.CurrentStoredPower >= aggregateDetails.MaxStoredPower)
            {
                CurrentState         = STATE_NORMAL;
                SinceLastStateChange = TimeSpan.FromSeconds(0);
                ZACommons.SetBatteryRecharge(batteries, false);
            }
            stateStr = "Disabled";
            break;
        }

        // See if we have a net power loss
        var newDraining = AddDrainData(aggregateDetails.CurrentPowerOutput > 0.0f);

        if (powerDrainHandler != null)
        {
            if (!Draining && newDraining)
            {
                powerDrainHandler.PowerDrainStarted(commons);
            }
            else if (Draining && !newDraining)
            {
                powerDrainHandler.PowerDrainEnded(commons);
            }
        }

        Draining = newDraining;

        commons.Echo(string.Format("Battery Manager: {0}", stateStr));
        commons.Echo(string.Format("Total Stored Power: {0}h", ZACommons.FormatPower(aggregateDetails.CurrentStoredPower)));
        commons.Echo(string.Format("Max Stored Power: {0}h", ZACommons.FormatPower(aggregateDetails.MaxStoredPower)));
        if (Draining)
        {
            commons.Echo("Net power loss!");
        }
    }
Beispiel #6
0
    public void Run(ZACommons commons)
    {
        // Only care about power producers on this ship
        var producers = ZACommons.GetBlocksOfType <IMyTerminalBlock>(commons.Blocks,
                                                                     block => block is IMyPowerProducer);

        // Limit to functional batteries
        var batteries = ZACommons.GetBlocksOfType <IMyBatteryBlock>(producers,
                                                                    battery => battery.IsFunctional);

        if (batteries.Count == 0)
        {
            return;                       // Nothing to do if no batteries to manage
        }
        // All other power producers
        var otherProducers = ZACommons.GetBlocksOfType <IMyTerminalBlock>(producers,
                                                                          block => !(block is IMyBatteryBlock));

        var batteryDetails = GetPowerDetails <IMyBatteryBlock>(batteries);
        var otherDetails   = GetPowerDetails <IMyTerminalBlock>(otherProducers);

        var totalDetails = batteryDetails + otherDetails;

        //commons.Echo("Battery Load: " + batteryDetails.ToString());
        //commons.Echo("Other Load: " + otherDetails.ToString());
        //commons.Echo("Total Load: " + totalDetails.ToString());

        // First, the degenerate cases...
        if (totalDetails.MaxPowerOutput == 0.0f)
        {
            return;                                      // Don't think this is possible...
        }
        if (otherDetails.MaxPowerOutput == 0.0f)
        {
            // Nothing but our batteries. Just put all batteries online.
            ZACommons.EnableBlocks(batteries, true);
            ZACommons.SetBatteryRecharge(batteries, false);
            return;
        }

        var totalLoad = totalDetails.CurrentPowerOutput / totalDetails.MaxPowerOutput;

        // If total system load exceeds threshold, attempt to bring a battery online.
        if (totalLoad > POWER_MANAGER_HIGH_LOAD_THRESHOLD)
        {
            QuietTimer = TimeSpan.FromSeconds(0);

            // Sort by stored power descending
            batteries.Sort(batteryComparerDesc);

            // Bring the first recharging battery online, shut down all other recharging batteries
            // (just shutting them down would probably free up a lot of power... need
            // separate case?)
            var found = false;
            for (var e = batteries.GetEnumerator(); e.MoveNext();)
            {
                var battery = e.Current;

                if (battery.Enabled && battery.ProductionEnabled)
                {
                    continue;                                               // Battery is already online, don't touch it
                }
                if (!found)
                {
                    // Found the first one, bring it online
                    if (!battery.Enabled)
                    {
                        battery.GetActionWithName("OnOff_On").Apply(battery);
                    }
                    ZACommons.SetBatteryRecharge(battery, false);
                    found = true;
                }
                else
                {
                    // Shut it down
                    if (battery.Enabled)
                    {
                        battery.GetActionWithName("OnOff_Off").Apply(battery);
                    }
                }
            }
        }
        else if (totalLoad < POWER_MANAGER_LOW_LOAD_THRESHOLD)
        {
            QuietTimer += commons.Program.ElapsedTime;

            if (QuietTimer >= QuietTimeout)
            {
                // NB We don't reset QuietTimer, so we will trigger at next tick again
                // (assuming load is still low)

                // Sort from low to high
                batteries.Sort(batteryComparer);

                // Any batteries actively discharging?
                if (batteryDetails.CurrentPowerOutput > 0.0f)
                {
                    // Take a battery offline, starting with the least charged.
                    // Note, we cannot actually start recharging until they are all offline
                    DisableOneBattery(batteries, totalDetails);
                }
                else
                {
                    // All batteries are down, enable one for charging
                    // (repeat next tick until we break low threshold, in which case QuietTimer
                    // will reset)
                    // But first, check if it would put us over the threshold
                    var first         = batteries[0];                                               // Assume all the same
                    var wouldBeOutput = otherDetails.CurrentPowerOutput + first.DefinedPowerOutput; // Assume MaxPowerOutput = MaxPowerInput (not available to us)
                    //commons.Echo("Would-be Output: " + ZACommons.FormatPower(wouldBeOutput));
                    var wouldBeLoad = wouldBeOutput / otherDetails.MaxPowerOutput;
                    //commons.Echo("Would-be Load: " + wouldBeLoad);

                    if (wouldBeLoad <= POWER_MANAGER_HIGH_LOAD_THRESHOLD)
                    {
                        RechargeOneBattery(batteries);
                    }
                }
            }
        }
        else
        {
            QuietTimer = TimeSpan.FromSeconds(0);
        }
    }