Skip to content

Commit

Permalink
Merge pull request #16 from emoncms/master
Browse files Browse the repository at this point in the history
Sync
  • Loading branch information
jpalo committed Feb 17, 2021
2 parents 73d58a0 + a216b3d commit 1680247
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 7 deletions.
45 changes: 45 additions & 0 deletions cli/cli_change_target_soc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php
// Load all emoncms and demandshaper requirements
define('EMONCMS_EXEC', 1);
include "/opt/emoncms/modules/demandshaper/cli/load_base.php";

// ------------------
$userid = 1;
$device_name = "openevse";
// ------------------

// Load schedule
$timezone = $user->get_timezone($userid);
$schedules = $demandshaper->get($userid);
$schedule = $schedules->$device_name;
$device_type = $schedule->settings->device_type;

// Change setting
$schedule->settings->target_soc = 0.8;

// Automatic update of time left for schedule e.g take into account updated battery SOC of electric car, home battery, device
$schedule = $device_class[$device_type]->auto_update_timeleft($schedule);

$kwh_required = ($schedule->settings->target_soc-$schedule->settings->current_soc)*$schedule->settings->battery_capacity;

// Print info
print "Current SOC:\t".($schedule->settings->current_soc*100)."%\n";
print "Target SOC:\t".($schedule->settings->target_soc*100)."%\n";
print "SOC Increase:\t".(($schedule->settings->target_soc-$schedule->settings->current_soc)*100)."% x ".$schedule->settings->battery_capacity." kWh battery capacity = ".$kwh_required." kWh\n";
print "Charge:\t\t".($kwh_required)." kWh @ ".$schedule->settings->charge_rate." kW = ".$schedule->settings->period." hrs\n";

// 1. Compile combined forecast
$combined = $demandshaper->get_combined_forecast($schedule->settings->forecast_config,$timezone);
// 2. Calculate forecast min/max
$combined = forecast_calc_min_max($combined);
// 3. Calculate schedule
if ($schedule->settings->interruptible) {
$schedule->runtime->periods = schedule_interruptible($combined,$schedule->runtime->timeleft,$schedule->settings->end_timestamp,$timezone);
} else {
$schedule->runtime->periods = schedule_block($combined,$schedule->runtime->timeleft,$schedule->settings->end_timestamp,$timezone);
}

print "Scheduled periods UTC: ".json_encode($schedule->runtime->periods)."\n";

$schedules->$device_name = $schedule;
$demandshaper->set($userid,$schedules);
49 changes: 49 additions & 0 deletions cli/load_base.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
define("MAX",1);
define("MIN",0);

chdir("/var/www/emoncms");
require "process_settings.php";
require "Lib/EmonLogger.php";
require "core.php";
require "$linked_modules_dir/demandshaper/lib/scheduler2.php";
require "$linked_modules_dir/demandshaper/lib/misc.php";
$log = new EmonLogger(__FILE__);

// -------------------------------------------------------------------------
// MYSQL, REDIS
// -------------------------------------------------------------------------
$mysqli = @new mysqli(
$settings["sql"]["server"],
$settings["sql"]["username"],
$settings["sql"]["password"],
$settings["sql"]["database"],
$settings["sql"]["port"]
);
if ( $mysqli->connect_error ) {
$log->error("Can't connect to database, please verify credentials/configuration in settings.php");
if ( $display_errors ) $log->error("Error message: ".$mysqli->connect_error);
die();
}

$redis = new Redis();
if (!$redis->connect($settings['redis']['host'], $settings['redis']['port'])) { $log->error("Can't connect to redis"); die; }
if (!empty($settings['redis']['prefix'])) $redis->setOption(Redis::OPT_PREFIX, $settings['redis']['prefix']);
if (!empty($settings['redis']['auth']) && !$redis->auth($settings['redis']['auth'])) {
$log->error("Can't connect to redis, autentication failed"); die;
}

// Load user module used to fetch user timezone
require("Modules/user/user_model.php");
$user = new User($mysqli,$redis);

require_once "Modules/device/device_model.php";
$device = new Device($mysqli,$redis);

require "Modules/demandshaper/demandshaper_model.php";
$demandshaper = new DemandShaper($mysqli,$redis,$device);

require_once "Modules/input/input_model.php";
$input = new Input($mysqli,$redis,false);

$device_class = $demandshaper->load_device_classes(false,$settings['mqtt']['basetopic']);
2 changes: 1 addition & 1 deletion demandshaper-module/Views/main.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@
<div class="openevse hide" style="border: 1px solid #ccc; padding:10px; margin-top:10px; background-color:#f0f0f0">
<p><b>OpenEVSE Settings</b></p>
<table class="table">
<tr><td>Control based on:</td><td><select class="input" name="soc_source"><option value="time">Charge time</option><option value="energy">Charge energy</option><option value="distance">Travel distance</option><option value="input">Battery charge level (Input)</option><option value="ovms">Battery charge level (OVMS)</option></select></td></tr>
<tr><td>Control based on:</td><td><select class="input" name="soc_source"><option value="time">Charge time</option><option value="energy">Charge energy</option><option value="distance">Travel distance</option><option value="input">Battery charge level (Input)</option><option value="ovms">Battery charge level (OVMS)</option><option value="api">set-device-settings api</option></select></td></tr>
<tr><td>Useable Battery Capacity:</td><td><input class="input" name="battery_capacity" type="text" style="width:80px"/> kWh</td></tr>
<tr><td>AC Charge Rate:</td><td><input class="input" name="charge_rate" type="text" style="width:80px"/> kW</td></tr>
<tr><td>Car economy:</td><td><input class="input" name="car_economy" type="text" style="width:80px"/> <span id="car_economy_units">miles/kWh</span></td></tr>
Expand Down
51 changes: 48 additions & 3 deletions demandshaper-module/demandshaper_controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

function demandshaper_controller()
{
global $mysqli, $redis, $session, $route, $settings, $linked_modules_dir, $user;
global $mysqli, $redis, $session, $route, $settings, $linked_modules_dir, $user, $input;
$result = false;

define("MAX",1);
Expand All @@ -35,8 +35,9 @@ function demandshaper_controller()

include "Modules/demandshaper/demandshaper_model.php";
$demandshaper = new DemandShaper($mysqli,$redis,$device);



require_once "Modules/input/input_model.php";
$input = new Input($mysqli,$redis,false);

if ($session['userid']) {
$timezone = $user->get_timezone($session['userid']);
Expand Down Expand Up @@ -167,6 +168,50 @@ function demandshaper_controller()
}
break;

case "set-device-settings":
if ($session["write"]) {
$route->format = "json";
if (!isset($_GET['device'])) return "device missing";
if (!isset($_GET['settings'])) return "settings missing";
$device_name = $_GET['device'];
$settings = json_decode($_GET['settings']);
if ($settings==null) return "invalid settings";

// Load schedule
$schedules = $demandshaper->get($session["userid"]);
if (!isset($schedules->$device_name)) return "device does not exist";
$schedule = $schedules->$device_name;
$device_type = $schedule->settings->device_type;

// Apply settings
foreach ($settings as $setting_name=>$setting_val) {
if (isset($schedule->settings->$setting_name)) $schedule->settings->$setting_name = $setting_val;
}

// Automatic update of time left for schedule e.g take into account updated battery SOC of electric car, home battery, device
$schedule = $demandshaper->device_class[$device_type]->auto_update_timeleft($schedule);

// 1. Compile combined forecast
$combined = $demandshaper->get_combined_forecast($schedule->settings->forecast_config,$timezone);
// 2. Calculate forecast min/max
require_once "$linked_modules_dir/demandshaper/lib/scheduler2.php";
$combined = forecast_calc_min_max($combined);
// 3. Calculate schedule
if ($schedule->settings->interruptible) {
$schedule->runtime->periods = schedule_interruptible($combined,$schedule->runtime->timeleft,$schedule->settings->end_timestamp,$timezone);
} else {
$schedule->runtime->periods = schedule_block($combined,$schedule->runtime->timeleft,$schedule->settings->end_timestamp,$timezone);
}
$schedule->runtime->started = false;

$schedules->$device_name = $schedule;
$demandshaper->set($session["userid"],$schedules);
$redis->rpush("demandshaper:trigger",$session["userid"]);

return $schedule->runtime;
}
break;

// Device list used for menu
case "list":
if (!$remoteaccess && $session["read"]) {
Expand Down
3 changes: 2 additions & 1 deletion demandshaper-module/js/openevse.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
function update_input_UI_openevse() {
$(".openevse").show();

if (schedule.settings.soc_source=="input" || schedule.settings.soc_source=="ovms") {
if (schedule.settings.soc_source=="input" || schedule.settings.soc_source=="ovms" || schedule.settings.soc_source=="api") {
$("#run_period").hide();
$("#charge_energy_div").hide();
$("#charge_distance_div").hide();
Expand Down Expand Up @@ -100,6 +100,7 @@ function openevse_calc_modes(reset_timeleft) {
if (schedule.settings.target_soc>1.0) schedule.settings.target_soc = 1.0
break;
case "input":
case "api":
case "ovms":
// 1. Start with current and target SOC
// 2. Charge energy
Expand Down
2 changes: 1 addition & 1 deletion demandshaper-module/module.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"name" : "DemandShaper",
"version" : "2.1.2"
"version" : "2.1.3"
}
3 changes: 2 additions & 1 deletion devices/openevse.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,14 @@ public function get_state($mqtt_request,$device,$timezone) {
}

public function auto_update_timeleft($schedule) {
$userid = 1;

if ((time()-$this->last_soc_update)>600 && $schedule->settings->soc_source!='time') {
$this->last_soc_update = time();

if ($schedule->settings->soc_source=='input') {
global $input;
if ($feedid = $input->exists_nodeid_name($userid,$device,"soc")) {
if ($feedid = $input->exists_nodeid_name($userid,"openevse","soc")) {
$schedule->settings->current_soc = $input->get_last_value($feedid)*0.01;
schedule_log("Recalculating EVSE schedule based on emoncms input: ".$schedule->settings->current_soc);
}
Expand Down

0 comments on commit 1680247

Please sign in to comment.