From dd4de35b3611ceea24bb58465a3c16920b259bdb Mon Sep 17 00:00:00 2001 From: Glyn Hudson Date: Thu, 24 Jan 2019 20:09:16 +0000 Subject: [PATCH] add dsicover end-point fix #209 --- platformio.ini | 2 +- src/data/home.htm | 2 +- src/data/style.css | 2 +- src/web_server.cpp | 17 ++++++++++++++--- src/web_server.home.htm.h | 2 +- src/web_server.style.css.h | 2 +- 6 files changed, 19 insertions(+), 8 deletions(-) diff --git a/platformio.ini b/platformio.ini index ecb563e..410733f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -30,7 +30,7 @@ data_dir = src/data env_default = openevse [common] -version = -DBUILD_TAG=2.7.7 +version = -DBUILD_TAG=2.7.8 monitor_speed=115200 lib_deps = PubSubClient@2.6, ESP Async WebServer@1.1.1, ESPAsyncTCP@1.1.3 extra_scripts = scripts/extra_script.py diff --git a/src/data/home.htm b/src/data/home.htm index ab67a4e..599b2db 100644 --- a/src/data/home.htm +++ b/src/data/home.htm @@ -1 +1 @@ - OpenEVSE

OpenEVSE

WiFi

Loading, please wait... (/)
\ No newline at end of file + OpenEVSE

OpenEVSE

WiFi

Loading, please wait... (/)
\ No newline at end of file diff --git a/src/data/style.css b/src/data/style.css index 4ce3b0c..cd4179a 100644 --- a/src/data/style.css +++ b/src/data/style.css @@ -1 +1 @@ -body{background-color:#fff;font-family:sans-serif;color:#333;font:14px Helvetica,sans-serif;box-sizing:border-box}#page{margin:20px;background-color:#fff}iframe{max-width:100%}table{width:100%;border-collapse:collapse}th{background-color:#777;color:#fff;border:1px solid #f1f1f1;padding:8px}td{background-color:#fff;color:#777;border:1px solid #e1e1e1;padding:8px}tr:nth-child(2n+2){background-color:#f3f3f3}.header{padding:20px}.header h1{padding-bottom:.3em;color:teal;font-size:45px;font-weight:normal;font-family:Garmond,"sans-serif";text-align:left;margin:0}.header h1 span{font-weight:bold;font-family:Garmond,"sans-serif";color:#000}h2{padding-bottom:.2em;border-bottom:1px solid #eee;margin-top:2px}.header h3{padding-top:-5px;padding-left:50px;font-weight:bold;font-family:Arial,"sans-serif";font-size:17px;color:#b6b6b6;margin:-25px 0 -5px 0}.box{padding:20px;border:1px solid #ddd;border-radius:1em 1em 1em 1em;box-shadow:1px 7px 7px 1px rgba(0,0,0,0.4);background:#fff;margin-bottom:20px}.box-full{margin:20px 20px 20px 20px;width:840px}.box-half{margin:20px 20px 20px 20px;width:380px}.box380{width:380px;padding:20px;margin:20px 20px 20px 20px;border:1px solid #ddd;border-radius:1em 1em 1em 1em;box-shadow:1px 7px 7px 1px rgba(0,0,0,0.4);background:#fff}.left{float:left;clear:left}.right{float:right;clear:right}@media(max-width:494px){#page{width:inherit;margin:5px auto}#content{padding:1px}.box380{margin:8px 8px 12px 8px;padding:10px;width:inherit;float:none}.box-full{margin:8px 8px 12px 8px;padding:10px;width:inherit;float:none}}@media(min-width:494px) and (max-width:980px){#page{width:465px;margin:0 auto}.box-full{width:380px}}@media(min-width:980px){#page{width:930px;margin:0 auto}}button{background-color:teal;border-radius:5px;box-shadow:0 2px 2px 0 rgba(0,0,0,0.4);border:0;color:#fff;padding:10px 28px;text-align:center;text-decoration:none;display:inline-block;font-size:1em;margin:4px 2px;cursor:pointer;outline:0}button:disabled{background-color:#eee;color:#ccc}button.on{background-color:#f1f1f1;color:#000}input[type="text"],input[type="password"],input[type="file"],input[type="time"],input[type="date"],select{box-sizing:border-box;border:1px solid #ddd;border-radius:4px;margin-top:10px;width:280px;padding:5px}input[type="time"]{width:110px}.setup input[type="time"]{width:110px}.setup input[type="date"]{width:164px}@media screen and (max-width:420px){input[type="text"],input[type="password"],select{width:240px}input[type="time"]{width:85px}input[type="date"]{width:174px}}#update{background-color:red}.container{height:inherit;padding-bottom:20px}.tabs{padding-bottom:4px;overflow:hidden}.tabs:after{content:" ";display:block;height:0;clear:both}.tabs input[type="radio"]{display:none}.tabs label{background:teal;border-radius:5px;box-shadow:0 2px 2px 0 rgba(0,0,0,0.4);color:#fff;cursor:pointer;display:block;float:left;font-size:1em;height:2.5em;line-height:2.5em;margin-right:.25em;padding:0 1.5em;text-align:center}.tabs input:hover+label{background:#e1e1e1;color:#000}.tabs input:checked+label{background:#f1f1f1;color:#000}#content{background:#e1e1e1;border-radius:.5em .5em .5em .5em;box-shadow:1px 7px 7px 1px rgba(0,0,0,0.4);display:block}#content:after{content:" ";display:block;height:0;clear:both}#footer{font-size:15px;text-align:center;margin-bottom:0}.small-text{font-size:10px;word-wrap:break-word}.saved{border-color:#3c763d !important;border-left-width:5px !important}.warning{border-left-color:#aa6708;border-left-width:5px}.warning h4{color:#aa6708;margin-top:0;margin-bottom:5px}.error{border-left-color:#a94442;border-left-width:5px}.error h4{color:#a94442;margin-top:0;margin-bottom:5px}.error td{color:#a94442}.error td:first-child{border-left-color:#a94442;border-left-width:5px}.switch{position:relative;display:inline-block;width:40px;height:24px;vertical-align:-40%}.switch input{display:none}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.4s;transition:.4s}.slider:before{position:absolute;content:"";height:16px;width:16px;left:4px;bottom:4px;background-color:white;-webkit-transition:.4s;transition:.4s}input:checked+.slider{background-color:teal}input:focus+.slider{box-shadow:0 0 1px teal}input:checked+.slider:before{-webkit-transform:translateX(16px);-ms-transform:translateX(16px);transform:translateX(16px)}.slider.round{border-radius:12px}.slider.round:before{border-radius:50%}.info{background-color:teal;border-radius:100%;color:#fff;display:inline-block;font-family:serif;font-size:12px;font-style:italic;height:16px;margin-left:16px;text-align:center;width:16px;vertical-align:20%}.info::before{content:"i"}span.selected{color:teal}.ready{border-color:#01c40e;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(1,196,14,0.3)}.connected{border-color:#d5ff70;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(213,255,112,0.4)}.charging{border-color:#0092f7;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(0,146,247,0.4)}.sleeping{border-color:#9200f7;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(146,0,247,0.4)}hr{height:1px;color:#eee;background-color:#eee;border:0}.updateBad{color:red}.updateGood{color:#32c832}.updateSlow{color:#f0b414}.updateSlower{color:#ff7d14} \ No newline at end of file +body{background-color:#fff;font-family:sans-serif;color:#333;font:14px Helvetica,sans-serif;box-sizing:border-box}#page{margin:20px;background-color:#fff}iframe{max-width:100%}table{width:100%;border-collapse:collapse}th{background-color:#777;color:#fff;border:1px solid #f1f1f1;padding:8px}td{background-color:#fff;color:#777;border:1px solid #e1e1e1;padding:8px}tr:nth-child(2n+2){background-color:#f3f3f3}.header{padding:20px}.header h1{padding-bottom:.3em;color:teal;font-size:45px;font-weight:normal;font-family:Garmond,"sans-serif";text-align:left;margin:0}.header h1 span{font-weight:bold;font-family:Garmond,"sans-serif";color:#000}h2{padding-bottom:.2em;border-bottom:1px solid #eee;margin-top:2px}.header h3{padding-top:-5px;padding-left:50px;font-weight:bold;font-family:Arial,"sans-serif";font-size:17px;color:#b6b6b6;margin:-25px 0 -5px 0}.box{padding:20px;border:1px solid #ddd;border-radius:1em 1em 1em 1em;box-shadow:1px 7px 7px 1px rgba(0,0,0,0.4);background:#fff;margin-bottom:20px}.box-full{margin:20px 20px 20px 20px;width:840px}.box-half{margin:20px 20px 20px 20px;width:380px}.box380{width:380px;padding:20px;margin:20px 20px 20px 20px;border:1px solid #ddd;border-radius:1em 1em 1em 1em;box-shadow:1px 7px 7px 1px rgba(0,0,0,0.4);background:#fff}.left{float:left;clear:left}.right{float:right;clear:right}@media(max-width:494px){#page{width:inherit;margin:5px auto}#content{padding:1px}.box380{margin:8px 8px 12px 8px;padding:10px;width:inherit;float:none}.box-full{margin:8px 8px 12px 8px;padding:10px;width:inherit;float:none}}@media(min-width:494px) and (max-width:980px){#page{width:465px;margin:0 auto}.box-full{width:380px}}@media(min-width:980px){#page{width:930px;margin:0 auto}}button{background-color:teal;border-radius:5px;box-shadow:0 2px 2px 0 rgba(0,0,0,0.4);border:0;color:#fff;padding:10px 28px;text-align:center;text-decoration:none;display:inline-block;font-size:1em;margin:4px 2px;cursor:pointer;outline:0}button:disabled{background-color:#eee;color:#ccc}button.on{background-color:#f1f1f1;color:#000}input[type="text"],input[type="password"],input[type="file"],input[type="time"],input[type="date"],select{box-sizing:border-box;border:1px solid #ddd;border-radius:4px;margin-top:10px;width:280px;padding:5px}input:optional{border-color:#ddd}input:required{border-color:#19a6ff}input:required:valid{border-color:#249c4a}input:required:valid+.validMessage{display:none}input:required+.validMessage{display:block;margin:5px 0}input[type="time"]{width:110px}.setup input[type="time"]{width:110px}.setup input[type="date"]{width:164px}@media screen and (max-width:420px){input[type="text"],input[type="password"],select{width:240px}input[type="time"]{width:85px}input[type="date"]{width:174px}}#update{background-color:red}.container{height:inherit;padding-bottom:20px}.tabs{padding-bottom:4px;overflow:hidden}.tabs:after{content:" ";display:block;height:0;clear:both}.tabs input[type="radio"]{display:none}.tabs label{background:teal;border-radius:5px;box-shadow:0 2px 2px 0 rgba(0,0,0,0.4);color:#fff;cursor:pointer;display:block;float:left;font-size:1em;height:2.5em;line-height:2.5em;margin-right:.25em;padding:0 1.5em;text-align:center}.tabs input:hover+label{background:#e1e1e1;color:#000}.tabs input:checked+label{background:#f1f1f1;color:#000}#content{background:#e1e1e1;border-radius:.5em .5em .5em .5em;box-shadow:1px 7px 7px 1px rgba(0,0,0,0.4);display:block}#content:after{content:" ";display:block;height:0;clear:both}#footer{font-size:15px;text-align:center;margin-bottom:0}.small-text{font-size:10px;word-wrap:break-word}.saved{border-color:#3c763d !important;border-left-width:5px !important}.warning{border-left-color:#aa6708;border-left-width:5px}.warning h4{color:#aa6708;margin-top:0;margin-bottom:5px}.error{border-left-color:#a94442;border-left-width:5px}.error h4{color:#a94442;margin-top:0;margin-bottom:5px}.error td{color:#a94442}.error td:first-child{border-left-color:#a94442;border-left-width:5px}.switch{position:relative;display:inline-block;width:40px;height:24px;vertical-align:-40%}.switch input{display:none}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.4s;transition:.4s}.slider:before{position:absolute;content:"";height:16px;width:16px;left:4px;bottom:4px;background-color:white;-webkit-transition:.4s;transition:.4s}input:checked+.slider{background-color:teal}input:focus+.slider{box-shadow:0 0 1px teal}input:checked+.slider:before{-webkit-transform:translateX(16px);-ms-transform:translateX(16px);transform:translateX(16px)}.slider.round{border-radius:12px}.slider.round:before{border-radius:50%}.info{background-color:teal;border-radius:100%;color:#fff;display:inline-block;font-family:serif;font-size:12px;font-style:italic;height:16px;margin-left:16px;text-align:center;width:16px;vertical-align:20%}.info::before{content:"i"}span.selected{color:teal}.ready{border-color:#01c40e;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(1,196,14,0.3)}.connected{border-color:#d5ff70;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(213,255,112,0.4)}.charging{border-color:#0092f7;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(0,146,247,0.4)}.sleeping{border-color:#9200f7;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(146,0,247,0.4)}hr{height:1px;color:#eee;background-color:#eee;border:0}.updateBad{color:red}.updateGood{color:#32c832}.updateSlow{color:#f0b414}.updateSlower{color:#ff7d14} \ No newline at end of file diff --git a/src/web_server.cpp b/src/web_server.cpp index 65b0653..b17f257 100644 --- a/src/web_server.cpp +++ b/src/web_server.cpp @@ -634,6 +634,7 @@ handleRst(AsyncWebServerRequest *request) { systemRebootTime = millis() + 1000; } + // ------------------------------------------------------------------- // Restart (Reboot) // url: /restart @@ -652,6 +653,18 @@ handleRestart(AsyncWebServerRequest *request) { systemRestartTime = millis() + 1000; } + +// ------------------------------------------------------------------- +// Emoncms describe end point, +// Allows local device discover using https://github.com/emoncms/find +// url: //emoncms/describe +// ------------------------------------------------------------------- +void handleDescribe(AsyncWebServerRequest *request) { + AsyncWebServerResponse *response = request->beginResponse(200, CONTENT_TYPE_TEXT, "openevse"); + response->addHeader("Access-Control-Allow-Origin", "*"); + request->send(response); +} + // ------------------------------------------------------------------- // Update firmware // url: /update @@ -922,16 +935,14 @@ web_server_setup() { server.on("/savemqtt", handleSaveMqtt); server.on("/saveadmin", handleSaveAdmin); server.on("/saveohmkey", handleSaveOhmkey); - server.on("/reset", handleRst); server.on("/restart", handleRestart); - server.on("/rapi", handleRapi); server.on("/r", handleRapi); - server.on("/scan", handleScan); server.on("/apoff", handleAPOff); server.on("/divertmode", handleDivertMode); + server.on("/emoncms/describe", handleDescribe); // Simple Firmware Update Form server.on("/update", HTTP_GET, handleUpdateGet); diff --git a/src/web_server.home.htm.h b/src/web_server.home.htm.h index 2f38fa3..5795794 100644 --- a/src/web_server.home.htm.h +++ b/src/web_server.home.htm.h @@ -1,2 +1,2 @@ static const char CONTENT_HOME_HTM[] PROGMEM = - " OpenEVSE

OpenEVSE

WiFi

Loading, please wait... (/)

WiFi Setup

Mode:

Network RSSI dBm

IP Address:

Successful packets:
of

OpenEVSE

RAPI packets:
of

Connect to network:

Select Network RSSI dBm
Scanning...

Passkey:

Connecting to WIFI Network...

Administration

Username:

Password:

Web interface HTTP authentication.

WiFi Firmware

ESP8266

Version:

Developer Mode

Enabled:

  Energy Monitoring

Emoncms Server*:

e.g: data.openevse.com/emoncms, emoncms.org, emonpi/emoncms

Emoncms Node*:

Emoncms write-apikey*:

Emoncms SSL SHA-1 Fingerprint (optional):


HTTPS will be enabled if present e.g: 7D:82:15:BE:D7:BC:72:58:87:7D:8E:40:D4:80:BA:1A:9F:8B:8D:DA

  Connected:    Successful posts: 

MQTT

Status published to:
{base-topic}/{status} value
e.g. /amp 16

RAPI control subscribes to:
{base-topic}/rapi/in/{command} value
e.g. /rapi/in/$SC 16
e.g. /rapi/in/$GC

RAPI response published to:
{base-topic}/rapi/out response
e.g. /rapi/out $OK 6 32

Host*:

e.g 'emonpi', 'test.mosquitto.org', '192.168.1.4'

Username: blank - no authentication

Password: blank - no authentication

Base-topic*:

e.g 'openevse'

Solar PV divert

Dynamically adjust charge rate based on solar PV generation or excess power (grid export).

1. Normal (default):

  • Charge at maximum current set by EVSE.
2. Eco:
  • If only solar PV feed available: charge rate is modulated based on solar PV generation.
  • If grid +I/-E (positive Import / negative Export) feed is available: charge rate will be modulated by available excess power.
  • If EVSE is sleeping: charging will begin when solar PV / excess power > min charge rate.
  • Charging will not pause; this avoids excess wear on the EVSE relay and the EV.
Note: It's assumed that EVSE power is included in the grid feed.

SolarPV-gen topic:
Solar PV MQTT topic to modulate charge rate based on solar

Grid (+I/-E) topic:

Grid (+I/-E) MQTT topic to modulate charge rate based on excess power

  Connected: 

  OhmConnect

Click Here to Join

OhmConnect monitors real-time conditions on the electricity grid. When dirty and unsustainable power plants turn on, our users receive a notification to save energy.

Ohm Hour:

Ohm key:

USA - California only

Ohm Key can be obtained by logging in to OhmConnect, enter Settings and locate the link in \"Open Source Projects\"
Example: https://login.ohmconnect.com/verify-ohm-hour/OpnEoVse
Key: OpnEoVse

EVSE Error

Session Status

Current Energy Temp Elapsed

Charge Options


Time limit:

Energy limit:



Timer:
Start:    Stop:

Energy

Energy
This Session:
Total:

Charge Mode

MQTT config not configured with Solar PV / Grid topic.

Solar PV Divert requires the SolarPV-gen or Grid (+I/-E) MQTT topic to be defined on the Services tab.
Dynamically adjust charge rate based on solar PV generation or excess power (grid export).

1. Normal (default):

  • Charge at maximum current set by EVSE.
2. Eco (solar PV divert):
  • If only solar PV feed available: charge rate is modulated based on solar PV generation.
  • If grid +I/-E (positive Import / negative Export) feed is available: charge rate will be modulated by available excess power.
  • If EVSE is sleeping: charging will begin when solar PV / excess power > min charge rate.
  • Charging will not pause; this avoids excess wear on the EVSE relay and the EV.
Note: It's assumed that EVSE power is included in the grid feed

Charging mode can also be set via MQTT:
{base-topic}/divertmode/set

Normal (max) Eco (PV divert)

Solar: Grid Import/Export: W - | Charge rate: A

Sensor Values

Sensor Value
Pilot:
Current Now:
Temp1:
Temp2:
Temp3:

Setup

Time: No RTC detected

Time:

Manual Automatic

Service Level:

Max Current:

Current

Name
Service Level:
Level Minimum:
Level Maximum:
Sensor Scale:
Sensor Offset:

Safety

Hardware safety checks. Enable dev mode (System > Developer Mode) to enable/disable or use the physical LCD + menu button.

Warning!!

Not all the safety tests are enabled, please take extra care before charging your vehicle.
Test Status
GFI Self Test:
Ground Monitoring:
Stuck Contact Detection:
Temperature Monitoring:
Diode Check:
Vent Required:
Error Count
GFCI:
No Ground:
Stuck Contact:

Hardware

OpenEVSE
Firmware:
Protocol:
OpenEVSE WiFi
Firmware:
Flash Size:
Free RAM:

Display

Simple Advanced

RAPI Command:

RAPI System Functions

Function Description
$FB LCD Backlight Color (0-7)
$FD Disable EVSE
$FE Enable EVSE
$FP Output text at x y position text to LCD (x y text)
$FR Reset EVSE
$FS Put EVSE to sleep

RAPI Get Commands

Get Description
$G3 Get Charge Time Limit, 15-minutes (1), 30-minutes (2), etc...
$GA Get Ammeter Scale/Offset, scale offset
$GC Get current capacity range, integers
$GE Get settings, amps flags
$GF Get fault counters, gfi ground stuck (in hex)
$GG Get charge current and voltage, milliamps millivolts
$GH Get charge limit in kWh, integer
$GM Get Voltmeter Scale/Offset, scale offset
$GO Get Overtemperature thresholds, ambient infrared
$GP Get Temperatures, LCD mcp9808 infrared (all integers, Celsius * 10)
$GS Get EVSE State, state elapsed_seconds
$GT Get time, year month day hour minute second
$GU Get Energy usage, wattseconds watt_hour_accumulated
$GV Get Versions, evse_firmware protocol_version

RAPI Set Commands

Set Description
$S0 Set LCD Type, Monochrome (0), Color (1)
$S1 Set RTC Year Month Day Hour Minute Second (all 2-digit max)
$S2 Enable (1)/ Disable (0) Ammeter Calibration Mode
$S3 Set Charge Time Limit, 15-minutes (1), 30-minutes (2), etc...
$SA Set Ammeter Scale/Offset, scale offset
$SC Set current capacity, integer
$SDEnable (1) / Disable (0) Diode self-check
$SF Enable (1) / Disable (0) GFI self-check
$SG Enable (1) / Disable (0) Ground check
$SH Set charge limit in kWh, integer
$SK Set accumulated Wh, integer
$SLSet service level (1/2/A)
$SM Set Voltmeter Scale/Offset, scale offset
$SO Set Overtemperature thresholds, ambient infrared
$SR Enable (1) / Disable (0) Stuck-relay check
$SS Enable (1) / Disable (0) GFI self-check
$ST Set timer, start_hour start_min end_hour end_min
$SV Enable (1) / Disable (0) vent required check
\n"; + " OpenEVSE

OpenEVSE

WiFi

Loading, please wait... (/)

WiFi Setup

Mode:

Network RSSI dBm

IP Address:

Successful packets:
of

OpenEVSE

RAPI packets:
of

Connect to network:

Select Network RSSI dBm
Scanning...

Passkey:

Connecting to WIFI Network...

Administration

Username:
15 characters max

Password:
15 characters max
Web interface HTTP authentication.

WiFi Firmware

ESP8266

Version:

Developer Mode

Enabled:

  Energy Monitoring

Emoncms Server*:

e.g: data.openevse.com/emoncms, emoncms.org, emonpi/emoncms

Emoncms Node*:

Emoncms write-apikey*:

Emoncms SSL SHA-1 Fingerprint (optional):


HTTPS will be enabled if present e.g: 7D:82:15:BE:D7:BC:72:58:87:7D:8E:40:D4:80:BA:1A:9F:8B:8D:DA

  Connected:    Successful posts: 

MQTT

Status published to:
{base-topic}/{status} value
e.g. /amp 16

RAPI control subscribes to:
{base-topic}/rapi/in/{command} value
e.g. /rapi/in/$SC 16
e.g. /rapi/in/$GC

RAPI response published to:
{base-topic}/rapi/out response
e.g. /rapi/out $OK 6 32

Host*:

e.g 'emonpi', 'test.mosquitto.org', '192.168.1.4'

Username: blank - no authentication

Password: blank - no authentication

Base-topic*:

e.g 'openevse'

Solar PV divert

Dynamically adjust charge rate based on solar PV generation or excess power (grid export).

1. Normal (default):

  • Charge at maximum current set by EVSE.
2. Eco:
  • If only solar PV feed available: charge rate is modulated based on solar PV generation.
  • If grid +I/-E (positive Import / negative Export) feed is available: charge rate will be modulated by available excess power.
  • If EVSE is sleeping: charging will begin when solar PV / excess power > min charge rate.
  • Charging will not pause; this avoids excess wear on the EVSE relay and the EV.
Note: It's assumed that EVSE power is included in the grid feed.

SolarPV-gen topic:
Solar PV MQTT topic to modulate charge rate based on solar

Grid (+I/-E) topic:

Grid (+I/-E) MQTT topic to modulate charge rate based on excess power

  Connected: 

  OhmConnect

Click Here to Join

OhmConnect monitors real-time conditions on the electricity grid. When dirty and unsustainable power plants turn on, our users receive a notification to save energy.

Ohm Hour:

Ohm key:

USA - California only

Ohm Key can be obtained by logging in to OhmConnect, enter Settings and locate the link in \"Open Source Projects\"
Example: https://login.ohmconnect.com/verify-ohm-hour/OpnEoVse
Key: OpnEoVse

EVSE Error

Session Status

Current Energy Temp Elapsed

Charge Options


Time limit:

Energy limit:



Timer:
Start:    Stop:

Energy

Energy
This Session:
Total:

Charge Mode

MQTT config not configured with Solar PV / Grid topic.

Solar PV Divert requires the SolarPV-gen or Grid (+I/-E) MQTT topic to be defined on the Services tab.
Dynamically adjust charge rate based on solar PV generation or excess power (grid export).

1. Normal (default):

  • Charge at maximum current set by EVSE.
2. Eco (solar PV divert):
  • If only solar PV feed available: charge rate is modulated based on solar PV generation.
  • If grid +I/-E (positive Import / negative Export) feed is available: charge rate will be modulated by available excess power.
  • If EVSE is sleeping: charging will begin when solar PV / excess power > min charge rate.
  • Charging will not pause; this avoids excess wear on the EVSE relay and the EV.
Note: It's assumed that EVSE power is included in the grid feed

Charging mode can also be set via MQTT:
{base-topic}/divertmode/set

Normal (max) Eco (PV divert)

Solar: Grid Import/Export: W - | Charge rate: A

Sensor Values

Sensor Value
Pilot:
Current Now:
Temp1:
Temp2:
Temp3:

Setup

Time: No RTC detected

Time:

Manual Automatic

Service Level:

Max Current:

Current

Name
Service Level:
Level Minimum:
Level Maximum:
Sensor Scale:
Sensor Offset:

Safety

Hardware safety checks. Enable dev mode (System > Developer Mode) to enable/disable or use the physical LCD + menu button.

Warning!!

Not all the safety tests are enabled, please take extra care before charging your vehicle.
Test Status
GFI Self Test:
Ground Monitoring:
Stuck Contact Detection:
Temperature Monitoring:
Diode Check:
Vent Required:
Error Count
GFCI:
No Ground:
Stuck Contact:

Hardware

OpenEVSE
Firmware:
Protocol:
OpenEVSE WiFi
Firmware:
Flash Size:
Free RAM:

Display

Simple Advanced

RAPI Command:

RAPI System Functions

Function Description
$FB LCD Backlight Color (0-7)
$FD Disable EVSE
$FE Enable EVSE
$FP Output text at x y position text to LCD (x y text)
$FR Reset EVSE
$FS Put EVSE to sleep

RAPI Get Commands

Get Description
$G3 Get Charge Time Limit, 15-minutes (1), 30-minutes (2), etc...
$GA Get Ammeter Scale/Offset, scale offset
$GC Get current capacity range, integers
$GE Get settings, amps flags
$GF Get fault counters, gfi ground stuck (in hex)
$GG Get charge current and voltage, milliamps millivolts
$GH Get charge limit in kWh, integer
$GM Get Voltmeter Scale/Offset, scale offset
$GO Get Overtemperature thresholds, ambient infrared
$GP Get Temperatures, LCD mcp9808 infrared (all integers, Celsius * 10)
$GS Get EVSE State, state elapsed_seconds
$GT Get time, year month day hour minute second
$GU Get Energy usage, wattseconds watt_hour_accumulated
$GV Get Versions, evse_firmware protocol_version

RAPI Set Commands

Set Description
$S0 Set LCD Type, Monochrome (0), Color (1)
$S1 Set RTC Year Month Day Hour Minute Second (all 2-digit max)
$S2 Enable (1)/ Disable (0) Ammeter Calibration Mode
$S3 Set Charge Time Limit, 15-minutes (1), 30-minutes (2), etc...
$SA Set Ammeter Scale/Offset, scale offset
$SC Set current capacity, integer
$SDEnable (1) / Disable (0) Diode self-check
$SF Enable (1) / Disable (0) GFI self-check
$SG Enable (1) / Disable (0) Ground check
$SH Set charge limit in kWh, integer
$SK Set accumulated Wh, integer
$SLSet service level (1/2/A)
$SM Set Voltmeter Scale/Offset, scale offset
$SO Set Overtemperature thresholds, ambient infrared
$SR Enable (1) / Disable (0) Stuck-relay check
$SS Enable (1) / Disable (0) GFI self-check
$ST Set timer, start_hour start_min end_hour end_min
$SV Enable (1) / Disable (0) vent required check
\n"; diff --git a/src/web_server.style.css.h b/src/web_server.style.css.h index 89f6826..62b129f 100644 --- a/src/web_server.style.css.h +++ b/src/web_server.style.css.h @@ -1,2 +1,2 @@ static const char CONTENT_STYLE_CSS[] PROGMEM = - "body{background-color:#fff;font-family:sans-serif;color:#333;font:14px Helvetica,sans-serif;box-sizing:border-box}#page{margin:20px;background-color:#fff}iframe{max-width:100%}table{width:100%;border-collapse:collapse}th{background-color:#777;color:#fff;border:1px solid #f1f1f1;padding:8px}td{background-color:#fff;color:#777;border:1px solid #e1e1e1;padding:8px}tr:nth-child(2n+2){background-color:#f3f3f3}.header{padding:20px}.header h1{padding-bottom:.3em;color:teal;font-size:45px;font-weight:normal;font-family:Garmond,\"sans-serif\";text-align:left;margin:0}.header h1 span{font-weight:bold;font-family:Garmond,\"sans-serif\";color:#000}h2{padding-bottom:.2em;border-bottom:1px solid #eee;margin-top:2px}.header h3{padding-top:-5px;padding-left:50px;font-weight:bold;font-family:Arial,\"sans-serif\";font-size:17px;color:#b6b6b6;margin:-25px 0 -5px 0}.box{padding:20px;border:1px solid #ddd;border-radius:1em 1em 1em 1em;box-shadow:1px 7px 7px 1px rgba(0,0,0,0.4);background:#fff;margin-bottom:20px}.box-full{margin:20px 20px 20px 20px;width:840px}.box-half{margin:20px 20px 20px 20px;width:380px}.box380{width:380px;padding:20px;margin:20px 20px 20px 20px;border:1px solid #ddd;border-radius:1em 1em 1em 1em;box-shadow:1px 7px 7px 1px rgba(0,0,0,0.4);background:#fff}.left{float:left;clear:left}.right{float:right;clear:right}@media(max-width:494px){#page{width:inherit;margin:5px auto}#content{padding:1px}.box380{margin:8px 8px 12px 8px;padding:10px;width:inherit;float:none}.box-full{margin:8px 8px 12px 8px;padding:10px;width:inherit;float:none}}@media(min-width:494px) and (max-width:980px){#page{width:465px;margin:0 auto}.box-full{width:380px}}@media(min-width:980px){#page{width:930px;margin:0 auto}}button{background-color:teal;border-radius:5px;box-shadow:0 2px 2px 0 rgba(0,0,0,0.4);border:0;color:#fff;padding:10px 28px;text-align:center;text-decoration:none;display:inline-block;font-size:1em;margin:4px 2px;cursor:pointer;outline:0}button:disabled{background-color:#eee;color:#ccc}button.on{background-color:#f1f1f1;color:#000}input[type=\"text\"],input[type=\"password\"],input[type=\"file\"],input[type=\"time\"],input[type=\"date\"],select{box-sizing:border-box;border:1px solid #ddd;border-radius:4px;margin-top:10px;width:280px;padding:5px}input[type=\"time\"]{width:110px}.setup input[type=\"time\"]{width:110px}.setup input[type=\"date\"]{width:164px}@media screen and (max-width:420px){input[type=\"text\"],input[type=\"password\"],select{width:240px}input[type=\"time\"]{width:85px}input[type=\"date\"]{width:174px}}#update{background-color:red}.container{height:inherit;padding-bottom:20px}.tabs{padding-bottom:4px;overflow:hidden}.tabs:after{content:\" \";display:block;height:0;clear:both}.tabs input[type=\"radio\"]{display:none}.tabs label{background:teal;border-radius:5px;box-shadow:0 2px 2px 0 rgba(0,0,0,0.4);color:#fff;cursor:pointer;display:block;float:left;font-size:1em;height:2.5em;line-height:2.5em;margin-right:.25em;padding:0 1.5em;text-align:center}.tabs input:hover+label{background:#e1e1e1;color:#000}.tabs input:checked+label{background:#f1f1f1;color:#000}#content{background:#e1e1e1;border-radius:.5em .5em .5em .5em;box-shadow:1px 7px 7px 1px rgba(0,0,0,0.4);display:block}#content:after{content:\" \";display:block;height:0;clear:both}#footer{font-size:15px;text-align:center;margin-bottom:0}.small-text{font-size:10px;word-wrap:break-word}.saved{border-color:#3c763d !important;border-left-width:5px !important}.warning{border-left-color:#aa6708;border-left-width:5px}.warning h4{color:#aa6708;margin-top:0;margin-bottom:5px}.error{border-left-color:#a94442;border-left-width:5px}.error h4{color:#a94442;margin-top:0;margin-bottom:5px}.error td{color:#a94442}.error td:first-child{border-left-color:#a94442;border-left-width:5px}.switch{position:relative;display:inline-block;width:40px;height:24px;vertical-align:-40%}.switch input{display:none}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.4s;transition:.4s}.slider:before{position:absolute;content:\"\";height:16px;width:16px;left:4px;bottom:4px;background-color:white;-webkit-transition:.4s;transition:.4s}input:checked+.slider{background-color:teal}input:focus+.slider{box-shadow:0 0 1px teal}input:checked+.slider:before{-webkit-transform:translateX(16px);-ms-transform:translateX(16px);transform:translateX(16px)}.slider.round{border-radius:12px}.slider.round:before{border-radius:50%}.info{background-color:teal;border-radius:100%;color:#fff;display:inline-block;font-family:serif;font-size:12px;font-style:italic;height:16px;margin-left:16px;text-align:center;width:16px;vertical-align:20%}.info::before{content:\"i\"}span.selected{color:teal}.ready{border-color:#01c40e;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(1,196,14,0.3)}.connected{border-color:#d5ff70;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(213,255,112,0.4)}.charging{border-color:#0092f7;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(0,146,247,0.4)}.sleeping{border-color:#9200f7;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(146,0,247,0.4)}hr{height:1px;color:#eee;background-color:#eee;border:0}.updateBad{color:red}.updateGood{color:#32c832}.updateSlow{color:#f0b414}.updateSlower{color:#ff7d14}\n"; + "body{background-color:#fff;font-family:sans-serif;color:#333;font:14px Helvetica,sans-serif;box-sizing:border-box}#page{margin:20px;background-color:#fff}iframe{max-width:100%}table{width:100%;border-collapse:collapse}th{background-color:#777;color:#fff;border:1px solid #f1f1f1;padding:8px}td{background-color:#fff;color:#777;border:1px solid #e1e1e1;padding:8px}tr:nth-child(2n+2){background-color:#f3f3f3}.header{padding:20px}.header h1{padding-bottom:.3em;color:teal;font-size:45px;font-weight:normal;font-family:Garmond,\"sans-serif\";text-align:left;margin:0}.header h1 span{font-weight:bold;font-family:Garmond,\"sans-serif\";color:#000}h2{padding-bottom:.2em;border-bottom:1px solid #eee;margin-top:2px}.header h3{padding-top:-5px;padding-left:50px;font-weight:bold;font-family:Arial,\"sans-serif\";font-size:17px;color:#b6b6b6;margin:-25px 0 -5px 0}.box{padding:20px;border:1px solid #ddd;border-radius:1em 1em 1em 1em;box-shadow:1px 7px 7px 1px rgba(0,0,0,0.4);background:#fff;margin-bottom:20px}.box-full{margin:20px 20px 20px 20px;width:840px}.box-half{margin:20px 20px 20px 20px;width:380px}.box380{width:380px;padding:20px;margin:20px 20px 20px 20px;border:1px solid #ddd;border-radius:1em 1em 1em 1em;box-shadow:1px 7px 7px 1px rgba(0,0,0,0.4);background:#fff}.left{float:left;clear:left}.right{float:right;clear:right}@media(max-width:494px){#page{width:inherit;margin:5px auto}#content{padding:1px}.box380{margin:8px 8px 12px 8px;padding:10px;width:inherit;float:none}.box-full{margin:8px 8px 12px 8px;padding:10px;width:inherit;float:none}}@media(min-width:494px) and (max-width:980px){#page{width:465px;margin:0 auto}.box-full{width:380px}}@media(min-width:980px){#page{width:930px;margin:0 auto}}button{background-color:teal;border-radius:5px;box-shadow:0 2px 2px 0 rgba(0,0,0,0.4);border:0;color:#fff;padding:10px 28px;text-align:center;text-decoration:none;display:inline-block;font-size:1em;margin:4px 2px;cursor:pointer;outline:0}button:disabled{background-color:#eee;color:#ccc}button.on{background-color:#f1f1f1;color:#000}input[type=\"text\"],input[type=\"password\"],input[type=\"file\"],input[type=\"time\"],input[type=\"date\"],select{box-sizing:border-box;border:1px solid #ddd;border-radius:4px;margin-top:10px;width:280px;padding:5px}input:optional{border-color:#ddd}input:required{border-color:#19a6ff}input:required:valid{border-color:#249c4a}input:required:valid+.validMessage{display:none}input:required+.validMessage{display:block;margin:5px 0}input[type=\"time\"]{width:110px}.setup input[type=\"time\"]{width:110px}.setup input[type=\"date\"]{width:164px}@media screen and (max-width:420px){input[type=\"text\"],input[type=\"password\"],select{width:240px}input[type=\"time\"]{width:85px}input[type=\"date\"]{width:174px}}#update{background-color:red}.container{height:inherit;padding-bottom:20px}.tabs{padding-bottom:4px;overflow:hidden}.tabs:after{content:\" \";display:block;height:0;clear:both}.tabs input[type=\"radio\"]{display:none}.tabs label{background:teal;border-radius:5px;box-shadow:0 2px 2px 0 rgba(0,0,0,0.4);color:#fff;cursor:pointer;display:block;float:left;font-size:1em;height:2.5em;line-height:2.5em;margin-right:.25em;padding:0 1.5em;text-align:center}.tabs input:hover+label{background:#e1e1e1;color:#000}.tabs input:checked+label{background:#f1f1f1;color:#000}#content{background:#e1e1e1;border-radius:.5em .5em .5em .5em;box-shadow:1px 7px 7px 1px rgba(0,0,0,0.4);display:block}#content:after{content:\" \";display:block;height:0;clear:both}#footer{font-size:15px;text-align:center;margin-bottom:0}.small-text{font-size:10px;word-wrap:break-word}.saved{border-color:#3c763d !important;border-left-width:5px !important}.warning{border-left-color:#aa6708;border-left-width:5px}.warning h4{color:#aa6708;margin-top:0;margin-bottom:5px}.error{border-left-color:#a94442;border-left-width:5px}.error h4{color:#a94442;margin-top:0;margin-bottom:5px}.error td{color:#a94442}.error td:first-child{border-left-color:#a94442;border-left-width:5px}.switch{position:relative;display:inline-block;width:40px;height:24px;vertical-align:-40%}.switch input{display:none}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.4s;transition:.4s}.slider:before{position:absolute;content:\"\";height:16px;width:16px;left:4px;bottom:4px;background-color:white;-webkit-transition:.4s;transition:.4s}input:checked+.slider{background-color:teal}input:focus+.slider{box-shadow:0 0 1px teal}input:checked+.slider:before{-webkit-transform:translateX(16px);-ms-transform:translateX(16px);transform:translateX(16px)}.slider.round{border-radius:12px}.slider.round:before{border-radius:50%}.info{background-color:teal;border-radius:100%;color:#fff;display:inline-block;font-family:serif;font-size:12px;font-style:italic;height:16px;margin-left:16px;text-align:center;width:16px;vertical-align:20%}.info::before{content:\"i\"}span.selected{color:teal}.ready{border-color:#01c40e;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(1,196,14,0.3)}.connected{border-color:#d5ff70;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(213,255,112,0.4)}.charging{border-color:#0092f7;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(0,146,247,0.4)}.sleeping{border-color:#9200f7;border-left-width:5px;box-shadow:1px 7px 7px 1px rgba(146,0,247,0.4)}hr{height:1px;color:#eee;background-color:#eee;border:0}.updateBad{color:red}.updateGood{color:#32c832}.updateSlow{color:#f0b414}.updateSlower{color:#ff7d14}\n";