Upgrade to go1.16, use go:embed for bundling assets (#555)

This commit is contained in:
andig 2021-02-21 11:15:52 +01:00 • committed by GitHub
parent b2ddbd4ff7
commit 3bb58e59e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 474 additions and 15605 deletions

View file

@ -13,15 +13,14 @@ jobs:
- name: Setup
uses: actions/setup-go@v2
with:
go-version: ^1.14
go-version: ^1.16
id: go
- uses: actions/cache@v2
with:
path: |
~/go/pkg/mod
**/node_modules
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}-${{ hashFiles('**/package-lock.json') }}
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
@ -34,7 +33,7 @@ jobs:
run: make install
- name: Assets & UI
run: make npm assets
run: make assets
- name: Porcelain
run: |
@ -52,13 +51,40 @@ jobs:
- name: Test
run: make test
build-ui:
name: Build UI
runs-on: ubuntu-latest
steps:
- uses: actions/cache@v2
with:
path: |
**/node_modules
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-
- name: Checkout
uses: actions/checkout@v2
- name: Install tools
run: make install-ui
- name: Assets & UI
run: make ui
- name: Porcelain
run: |
test -z "$(git status --porcelain)" || (git status; git diff; false)
dockerlatest:
name: Publish :latest
if: |
startsWith(github.ref, 'refs/heads/master')
&& ! contains(github.head_ref, 'refs/heads/chore/')
needs: build
needs:
- build
- build-ui
runs-on: ubuntu-latest
steps:
@ -83,7 +109,9 @@ jobs:
dockerrelease:
name: Publish :release
if: "startsWith(github.ref, 'refs/tags')"
needs: build
needs:
- build
- build-ui
runs-on: ubuntu-latest
steps:
@ -109,7 +137,9 @@ jobs:
release:
name: Release
if: "startsWith(github.ref, 'refs/tags')"
needs: build
needs:
- build
- build-ui
runs-on: ubuntu-latest
steps:

1
.gitignore vendored
View file

@ -13,5 +13,4 @@ evcc_*
flags/*
buildflags/*
linux-*.Dockerfile
dist
node_modules

View file

@ -2,9 +2,6 @@ release:
github:
owner: andig
name: evcc
# before:
# hooks:
# - make npm assets
extra_files:
- glob: evcc_*.image.gz
- glob: evcc_*.rootfs.gz

View file

@ -1,39 +1,50 @@
#
# STEP 1 build executable binary
#
# STEP 1 build ui
FROM node:14-alpine as node
FROM golang:1.14-alpine as builder
# Install git + SSL ca certificates.
# Git is required for fetching the dependencies.
# Ca-certificates is required to call HTTPS endpoints.
RUN apk update && apk add --no-cache git ca-certificates tzdata alpine-sdk npm && update-ca-certificates
RUN apk update && apk add --no-cache make
WORKDIR /build
# cache modules
COPY go.mod .
COPY go.sum .
RUN go mod download
# install go and node tools
# install node tools
COPY Makefile .
COPY package*.json ./
RUN make install
RUN make install-ui
# build ui
COPY assets assets
COPY vue.config.js vue.config.js
RUN make clean npm
RUN make clean ui
# STEP 2 build executable binary
FROM golang:1.16-alpine as builder
# Install git + SSL ca certificates.
# Git is required for fetching the dependencies.
# Ca-certificates is required to call HTTPS endpoints.
RUN apk update && apk add --no-cache git ca-certificates tzdata alpine-sdk && update-ca-certificates
WORKDIR /build
# install go tools and cache modules
COPY Makefile .
COPY go.mod .
COPY go.sum .
RUN make install
RUN go mod download
# prepare
COPY . .
RUN make assets
# copy ui
COPY --from=node /build/dist /build/dist
# build
RUN make build
#
# STEP 2 build a small image including module support
#
# STEP 3 build a small image including module support
FROM alpine:3.12
WORKDIR /evcc

View file

@ -1,6 +1,6 @@
.PHONY: default clean install lint test assets build binaries test-release release
.PHONY: publish-testing publish-latest publish-images
.PHONY: image image-rootfs image-update
.PHONY: default all clean install install-ui ui assets lint test build test-release release
.PHONY: docker publish-testing publish-latest publish-images
.PHONY: prepare-image image-rootfs image-update
# build vars
TAG_NAME := $(shell test -d .git && git describe --abbrev=0 --tags)
@ -13,7 +13,7 @@ BUILD_ARGS := -ldflags='$(LD_FLAGS)'
# docker
DOCKER_IMAGE := andig/evcc
ALPINE_VERSION := 3.12
ALPINE_VERSION := 3.13
TARGETS := arm.v6,arm.v8,amd64
# image
@ -21,16 +21,25 @@ IMAGE_FILE := evcc_$(TAG_NAME).image
IMAGE_ROOTFS := evcc_$(TAG_NAME).rootfs
IMAGE_OPTIONS := -hostname evcc -http_port 8080 github.com/gokrazy/serial-busybox github.com/gokrazy/breakglass github.com/andig/evcc
default: clean install npm assets lint test build
default: build
all: clean install install-ui ui assets lint test build
clean:
rm -rf dist/
install:
go install github.com/mjibson/esc
go install github.com/golang/mock/mockgen
install-ui:
npm ci
ui:
npm run build
assets:
go generate ./...
lint:
golangci-lint run
npm run lint
@ -39,17 +48,6 @@ test:
@echo "Running testsuite"
go test ./...
npm:
npm run build
ui:
npm run build
go generate main.go
assets:
@echo "Generating embedded assets"
go generate ./...
build:
@echo Version: $(VERSION) $(BUILD_DATE)
go build -v $(BUILD_TAGS) $(BUILD_ARGS)
@ -60,6 +58,10 @@ release-test:
release:
goreleaser --rm-dist
docker:
@echo Version: $(VERSION) $(BUILD_DATE)
docker build --tag $(DOCKER_IMAGE):testing .
publish-testing:
@echo Version: $(VERSION) $(BUILD_DATE)
seihon publish --dry-run=false --template docker/tmpl.Dockerfile --base-runtime-image alpine:$(ALPINE_VERSION) \

View file

@ -104,7 +104,7 @@ When using Docker with a device that requires multicast UDP like SMA, make sure
docker run --network host andig/evcc ...
```
To build EVCC from source, [Go](2) 1.13 and [Node](3) 14 are required:
To build EVCC from source, [Go](2) 1.16 and [Node](3) 14 are required:
make

View file

@ -1,127 +1,15 @@
package cmd
import (
_ "embed" // for yaml
"fmt"
"github.com/spf13/viper"
"gopkg.in/yaml.v3"
)
const demoYaml = `
log: info
javascript:
- vm: shared
script: |
state = {
residualpower: 200,
pvpower: -3000,
batterypower: 200,
gridpower: -2000,
chargepower: 0,
maxcurrent: 0,
battery: 63, // car
};
function get() {
console.log("state:", JSON.stringify(state));
}
function set() {
console.log(param+":", val);
console.log("state:", JSON.stringify(state));
}
meters:
- name: grid
type: default
power:
type: js
vm: shared
script: state.gridpower = state.pvpower + state.chargepower + state.residualpower + state.batterypower;
- name: pv
type: default
power:
type: js
vm: shared
script: state.pvpower += 100*Math.random();
- name: battery
type: default
power:
type: js
vm: shared
script: state.batterypower;
soc:
type: js
vm: shared
script: "30"
- name: charge
type: default
power:
type: js
vm: shared
script: state.chargepower;
soc:
type: js
vm: shared
script: "30"
chargers:
- name: demo
type: default
enable:
type: js
vm: shared
script: |
set();
state.enabled = val;
if (state.enabled) state.chargepower = state.maxcurrent * 230; else state.chargepower = 0;
enabled:
type: js
vm: shared
script: |
state.enabled;
status:
type: js
vm: shared
script: |
if (state.enabled) "C"; else "B";
maxcurrent:
type: js
vm: shared
script: |
set();
state.maxcurrent = val;
if (state.enabled) state.chargepower = state.maxcurrent * 230;
vehicles:
- name: demo
title: e-Golf
type: default
charge:
type: js
vm: shared
script: |
if (state.chargepower > 0) state.battery++; else state.battery--;
if (state.battery < 15) state.battery = 15;
if (state.battery > 100) state.battery = 100;
state.battery;
cache: 1s
site:
title: Demo
meters:
grid: grid
pv: pv
battery: battery
loadpoints:
- title: Carport
charger: demo
meters:
charge: charge
vehicle: demo
`
//go:embed demo.yaml
var demoYaml string
func demoConfig() (conf config) {
demo := map[string]interface{}{}

113
cmd/demo.yaml Normal file
View file

@ -0,0 +1,113 @@
log: info
javascript:
- vm: shared
script: |
state = {
residualpower: 200,
pvpower: -3000,
batterypower: 200,
gridpower: -2000,
chargepower: 0,
maxcurrent: 0,
battery: 63, // car
};
function get() {
console.log("state:", JSON.stringify(state));
}
function set() {
console.log(param+":", val);
console.log("state:", JSON.stringify(state));
}
meters:
- name: grid
type: default
power:
type: js
vm: shared
script: state.gridpower = state.pvpower + state.chargepower + state.residualpower + state.batterypower;
- name: pv
type: default
power:
type: js
vm: shared
script: state.pvpower += 100*Math.random();
- name: battery
type: default
power:
type: js
vm: shared
script: state.batterypower;
soc:
type: js
vm: shared
script: "30"
- name: charge
type: default
power:
type: js
vm: shared
script: state.chargepower;
soc:
type: js
vm: shared
script: "30"
chargers:
- name: demo
type: default
enable:
type: js
vm: shared
script: |
set();
state.enabled = val;
if (state.enabled) state.chargepower = state.maxcurrent * 230; else state.chargepower = 0;
enabled:
type: js
vm: shared
script: |
state.enabled;
status:
type: js
vm: shared
script: |
if (state.enabled) "C"; else "B";
maxcurrent:
type: js
vm: shared
script: |
set();
state.maxcurrent = val;
if (state.enabled) state.chargepower = state.maxcurrent * 230;
vehicles:
- name: demo
title: e-Golf
type: default
charge:
type: js
vm: shared
script: |
if (state.chargepower > 0) state.battery++; else state.battery--;
if (state.battery < 15) state.battery = 15;
if (state.battery > 100) state.battery = 100;
state.battery;
cache: 1s
site:
title: Demo
meters:
grid: grid
pv: pv
battery: battery
loadpoints:
- title: Carport
charger: demo
meters:
charge: charge
vehicle: demo

6
dist/css/chunk-vendors.c5b0137c.css vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/css/index.4716cdc1.css vendored Normal file
View file

@ -0,0 +1 @@
.progress-bar-animated{animation-direction:reverse}.btn.caption{opacity:1}.btn.first{border-top-left-radius:.2rem;border-bottom-left-radius:.2rem}code{font-size:87.5%;color:#e83e8c;word-wrap:break-word}.value,input[type=radio],label.btn{white-space:nowrap!important}.text-muted a,.text-muted a:hover{color:#6c757d!important;text-decoration:none}.bg-muted{opacity:.25}.fade-enter-active[data-v-4b17e482],.fade-leave-active[data-v-4b17e482]{transition:opacity .25s ease-in}.fade-enter[data-v-4b17e482],.fade-leave-to[data-v-4b17e482]{opacity:0}.dialog[data-v-4b17e482]{position:fixed;top:0;left:0;z-index:1050;width:100%;height:100%;overflow:hidden;outline:0}.display-enter-active[data-v-4b17e482]{display:block!important}.expand-icon[data-v-4b17e482]{transition:transform .25s ease-in;transform:rotate(0)}.expand-icon-rotated[data-v-4b17e482]{transform:rotate(-180deg)}

BIN
dist/ico/android-chrome-192x192.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
dist/ico/android-chrome-512x512.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
dist/ico/apple-touch-icon.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

9
dist/ico/browserconfig.xml vendored Normal file
View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="ico/mstile-150x150.png"/>
<TileColor>#2b5797</TileColor>
</tile>
</msapplication>
</browserconfig>

BIN
dist/ico/favicon-16x16.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

BIN
dist/ico/favicon-32x32.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
dist/ico/favicon.ico vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

27
dist/ico/favicon.svg vendored Normal file
View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" viewBox="0 0 576 512" version="1.1" id="svg12"
sodipodi:docname="leaf.svg" inkscape:version="1.0beta2 (2b71d25, 2019-12-03)">
<metadata id="metadata18">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs id="defs16" />
<sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" inkscape:document-rotation="0" borderopacity="1"
objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2"
inkscape:window-width="1280" inkscape:window-height="755" id="namedview14" showgrid="false"
inkscape:zoom="0.92768596" inkscape:cx="353.312" inkscape:cy="200.09826" inkscape:window-x="0"
inkscape:window-y="23" inkscape:window-maximized="0" inkscape:current-layer="svg12" />
<path style="stroke-width:1.1;stroke-miterlimit:4;stroke-dasharray:none"
d="M546.2 9.7c-5.6-12.5-21.6-13-28.3-1.2C486.9 62.4 431.4 96 368 96h-80C182 96 96 182 96 288c0 7 .8 13.7 1.5 20.5C161.3 262.8 253.4 224 384 224c8.8 0 16 7.2 16 16s-7.2 16-16 16C132.6 256 26 410.1 2.4 468c-6.6 16.3 1.2 34.9 17.5 41.6 16.4 6.8 35-1.1 41.8-17.3 1.5-3.6 20.9-47.9 71.9-90.6 32.4 43.9 94 85.8 174.9 77.2C465.5 467.5 576 326.7 576 154.3c0-50.2-10.8-102.2-29.8-144.6z"
id="path10" />
<path inkscape:connector-curvature="0" id="path20"
d="m 21.21449,509.39751 c -5.971286,-2.52059 -9.269565,-4.81794 -12.9733928,-9.03637 -6.1766191,-7.03478 -8.8842152,-17.3518 -6.971629,-26.56467 1.258445,-6.0619 11.8107088,-27.39624 19.8175918,-40.06678 22.713423,-35.94297 56.773767,-71.44959 94.11207,-98.10823 68.76834,-49.09895 154.92997,-76.24193 249.47048,-78.5892 11.23532,-0.27896 21.89988,-0.8765 23.69902,-1.32786 4.02501,-1.0098 9.1941,-5.41782 10.76663,-9.18141 2.92101,-6.99096 0.29781,-15.90466 -5.87906,-19.97721 l -3.71288,-2.44799 -20.91224,0.12879 c -95.91234,0.59069 -191.38366,28.82528 -262.4752,77.62416 -4.25115,2.91809 -7.89194,5.14304 -8.090638,4.94433 -1.034492,-1.03449 -1.681776,-19.91176 -1.047227,-30.54108 4.946935,-82.86599 63.514115,-153.47981 144.215265,-173.87878 19.41459,-4.90746 20.47839,-4.979088 83.88455,-5.648034 49.15213,-0.518563 60.64802,-0.871339 68.23769,-2.09402 19.39657,-3.124747 35.56867,-8.269165 52.1562,-16.591125 29.26858,-14.684035 50.80653,-34.823142 71.56328,-66.915381 3.64477,-5.6352221 5.2829,-7.343539 8.63712,-9.0071805 5.61954,-2.78721054 10.73552,-2.07507421 15.40609,2.1445063 3.91499,3.5369576 8.97418,14.4546312 15.06776,32.5161072 20.64772,61.200058 24.79308,128.916947 11.83935,193.402597 -25.37559,126.32372 -112.033,220.27326 -224.43817,243.32443 -17.6222,3.61382 -29.64707,4.91447 -50.19768,5.42955 -21.4123,0.53668 -32.33232,-0.45528 -49.11375,-4.46143 -40.56718,-9.6844 -78.7741,-33.83895 -104.95018,-66.34986 l -5.80657,-7.21182 -7.6437,6.87084 c -26.141169,23.49803 -48.851538,52.36799 -61.996828,78.81184 -2.979862,5.99446 -6.952342,12.64221 -8.827734,14.77277 -7.841316,8.90821 -23.148129,12.54014 -33.836218,8.02851 z"
style="fill:#007bff;stroke:#007bff;stroke-width:1.1;fill-opacity:1;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
dist/ico/mstile-150x150.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

47
dist/ico/safari-pinned-tab.svg vendored Normal file
View file

@ -0,0 +1,47 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="576.000000pt" height="576.000000pt"
viewBox="0 0 576.000000 576.000000" preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,576.000000) scale(0.100000,-0.100000)" fill="#000000" stroke="none">
<path d="M5254 5426 c-30 -14 -94 -84 -94 -105 0 -6 -4 -11 -10 -11 -5 0 -10
-4 -10 -10 0 -9 -64 -106 -80 -120 -3 -3 -21 -25 -40 -50 -147 -191 -344 -351
-572 -466 -70 -35 -236 -103 -268 -109 -8 -2 -35 -9 -60 -16 -53 -15 -54 -15
-100 -23 -19 -3 -46 -8 -60 -11 -55 -12 -115 -16 -330 -20 -124 -2 -227 -5
-230 -6 -3 -1 -8 -1 -11 -1 -9 1 -102 2 -121 1 -10 0 -111 0 -225 0 -217 1
-326 -3 -409 -14 -27 -4 -60 -8 -74 -9 -38 -5 -261 -63 -295 -77 -16 -7 -36
-13 -43 -15 -26 -5 -147 -59 -232 -102 -258 -134 -488 -334 -672 -586 -21 -28
-42 -57 -48 -63 -6 -7 -7 -13 -3 -13 4 0 3 -4 -3 -8 -13 -8 -71 -110 -118
-209 -66 -137 -131 -333 -151 -453 -3 -19 -8 -46 -10 -60 -20 -105 -30 -283
-21 -400 2 -25 4 -59 5 -77 1 -26 4 -30 20 -26 11 3 27 14 37 24 9 10 20 19
24 19 4 0 36 19 71 43 90 60 168 107 173 104 2 -1 12 6 23 15 27 25 416 221
463 233 3 1 16 6 30 12 171 73 503 184 620 208 8 2 15 4 15 5 0 2 21 7 60 15
17 3 46 10 65 15 19 5 46 11 60 14 14 3 48 11 75 16 28 6 64 13 80 16 54 9 69
11 110 18 23 3 52 9 65 11 28 5 89 13 250 31 129 14 341 25 549 27 137 2 152
-1 193 -43 47 -48 57 -146 19 -196 -48 -65 -67 -69 -351 -78 -141 -5 -210 -9
-335 -22 -33 -3 -76 -7 -95 -9 -19 -2 -51 -6 -70 -9 -19 -3 -57 -8 -84 -11
-27 -3 -52 -8 -55 -9 -3 -2 -28 -6 -56 -10 -27 -3 -63 -9 -80 -12 -16 -4 -37
-7 -45 -8 -9 -1 -21 -5 -28 -10 -6 -4 -12 -5 -12 -3 0 3 -37 -4 -82 -14 -46
-11 -94 -22 -108 -25 -106 -22 -487 -144 -577 -185 -23 -10 -44 -19 -47 -19
-22 0 -467 -220 -486 -240 -3 -3 -21 -14 -40 -24 -68 -37 -237 -150 -345 -231
-236 -177 -480 -412 -653 -629 -31 -39 -60 -73 -63 -76 -4 -3 -50 -70 -103
-149 -99 -148 -210 -356 -240 -448 -48 -147 25 -313 169 -383 41 -20 66 -24
135 -25 75 0 92 4 144 30 71 36 115 85 168 190 137 272 288 476 530 715 53 52
113 110 135 128 l38 33 18 -23 c91 -116 214 -241 320 -325 40 -32 74 -60 77
-63 18 -19 249 -160 262 -160 5 0 22 -8 36 -18 35 -24 240 -105 295 -117 10
-2 27 -7 37 -10 10 -3 28 -8 39 -10 12 -3 31 -7 44 -11 22 -5 47 -10 102 -19
17 -3 41 -7 55 -10 14 -3 78 -7 143 -10 65 -3 121 -6 125 -6 4 -1 9 -1 12 0 3
1 44 3 91 5 101 5 251 19 309 30 14 3 43 8 65 11 22 3 47 7 55 10 8 2 26 6 40
9 85 14 355 97 447 137 24 10 44 18 46 18 13 -4 319 165 411 226 66 44 126 85
135 90 8 6 24 18 35 27 12 10 55 46 96 80 114 95 261 243 365 369 44 53 155
199 155 204 0 3 18 30 40 60 22 30 40 56 40 59 0 2 22 41 49 85 48 78 175 331
201 401 7 19 17 39 22 44 4 6 8 16 8 24 0 8 6 28 14 45 15 34 28 70 27 75 -1
1 6 19 15 40 8 20 17 44 19 52 2 8 13 49 25 90 24 82 57 209 64 249 3 14 7 37
11 51 3 14 8 36 10 50 2 14 6 36 9 50 6 34 16 97 21 140 3 19 7 55 10 79 16
121 19 198 19 446 -1 238 -4 308 -20 430 -2 17 -5 49 -8 72 -2 23 -7 55 -10
70 -3 15 -8 48 -12 73 -3 24 -7 48 -10 51 -2 4 -6 24 -10 45 -19 130 -124 484
-181 614 -57 130 -81 162 -130 181 -34 13 -82 11 -119 -5z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

20
dist/ico/site.webmanifest vendored Normal file
View file

@ -0,0 +1,20 @@
{
"start_url": "../",
"name": "EV Charge Controller",
"short_name": "EV Charge Controller",
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone",
"icons": [
{
"src": "android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}

4
dist/index.html vendored Normal file
View file

@ -0,0 +1,4 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="description" content="EV Charge Controller"><meta name="author" content="andig"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><link rel="apple-touch-icon" sizes="180x180" href="ico/apple-touch-icon.png"><link rel="icon" type="image/png" sizes="32x32" href="ico/favicon-32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="ico/favicon-16x16.png"><link rel="manifest" href="ico/site.webmanifest"><link rel="mask-icon" href="ico/safari-pinned-tab.svg" color="#5bbad5"><link rel="shortcut icon" href="ico/favicon.ico"><meta name="msapplication-TileColor" content="#2b5797"><meta name="msapplication-config" content="ico/browserconfig.xml"><meta name="theme-color" content="#ffffff"><title>evcc</title><link href="css/chunk-vendors.c5b0137c.css" rel="preload" as="style"><link href="css/index.4716cdc1.css" rel="preload" as="style"><link href="js/chunk-vendors.7c84295f.js" rel="preload" as="script"><link href="js/index.bf403928.js" rel="preload" as="script"><link href="css/chunk-vendors.c5b0137c.css" rel="stylesheet"><link href="css/index.4716cdc1.css" rel="stylesheet"></head><body><script>window.evcc = {
version: "[[.Version]]",
configured: "[[.Configured]]",
};</script><div id="app"></div><div id="toasts"></div><footer class="pt-4 pb-2 pt-md-5 pb-md-4 mt-3 mt-md-5 border-top"><div class="container"><div class="row"><div class="col-6"><small class="text-muted"><a href="https://github.com/andig/evcc/releases/tag/[[.Version]]">[[.Version]]</a> (<a href="https://github.com/andig/evcc/commit/[[.Commit]]">[[.Commit]]</a>)</small></div><div class="col-6 text-right"><small class="text-muted">&copy; 2020</small></div></div></div></footer><script src="js/chunk-vendors.7c84295f.js"></script><script src="js/index.bf403928.js"></script></body></html>

78
dist/js/chunk-vendors.7c84295f.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/js/chunk-vendors.7c84295f.js.map vendored Normal file

File diff suppressed because one or more lines are too long

2
dist/js/index.bf403928.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/js/index.bf403928.js.map vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -1,37 +1,52 @@
############################
# STEP 1 build executable binary
############################
FROM golang:1.14-alpine as builder
# STEP 1 build ui
FROM node:14-alpine as node
# Install git + SSL ca certificates.
# Git is required for fetching the dependencies.
# Ca-certificates is required to call HTTPS endpoints.
RUN apk update && apk add --no-cache git ca-certificates tzdata alpine-sdk npm && update-ca-certificates
RUN apk update && apk add --no-cache make
WORKDIR /build
# cache modules
COPY go.mod .
COPY go.sum .
RUN go mod download
# install go and node tools
# install node tools
COPY Makefile .
COPY package*.json ./
RUN make install
RUN make install-ui
# build ui
COPY assets assets
COPY vue.config.js vue.config.js
RUN make clean npm
RUN make clean ui
# STEP 2 build executable binary
FROM golang:1.16-alpine as builder
# Install git + SSL ca certificates.
# Git is required for fetching the dependencies.
# Ca-certificates is required to call HTTPS endpoints.
RUN apk update && apk add --no-cache git ca-certificates tzdata alpine-sdk && update-ca-certificates
WORKDIR /build
# install go tools and cache modules
COPY Makefile .
COPY go.mod .
COPY go.sum .
RUN make install
RUN go mod download
# prepare
COPY . .
RUN make assets
# copy ui
COPY --from=node /build/dist /build/dist
# build
COPY . .
RUN make assets
RUN GOARCH={{ .GoARCH }} GOARM={{ .GoARM }} make build
#############################
## STEP 2 build a small image
#############################
# STEP 3 build a small image including module support
FROM {{ .RuntimeImage }}
ENV TZ=Europe/Berlin

3
go.mod
View file

@ -1,6 +1,6 @@
module github.com/andig/evcc
go 1.13
go 1.16
require (
github.com/PuerkitoBio/goquery v1.6.1
@ -38,7 +38,6 @@ require (
github.com/lorenzodonini/ocpp-go v0.12.1-0.20201122163044-c8e61b6f96d2
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
github.com/mitchellh/mapstructure v1.4.1
github.com/mjibson/esc v0.2.0
github.com/muka/go-bluetooth v0.0.0-20201211051136-07f31c601d33
github.com/mxschmitt/golang-combinations v1.1.0
github.com/nirasan/go-oauth-pkce-code-verifier v0.0.0-20170819232839-0fbfe93532da

2
go.sum
View file

@ -137,7 +137,6 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-ping/ping v0.0.0-20201022122018-3977ed72668a h1:O9xspHB2yrvKfMQ1m6OQhqe37i5yvg0dXAYMuAjugmM=
github.com/go-ping/ping v0.0.0-20201022122018-3977ed72668a/go.mod h1:35JbSyV/BYqHwwRA6Zr1uVDm1637YlNOU61wI797NPI=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
@ -365,7 +364,6 @@ github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mjibson/esc v0.2.0 h1:k96hdaR9Z+nMcnDwNrOvhdBqtjyMrbVyxLpsRCdP2mA=
github.com/mjibson/esc v0.2.0/go.mod h1:9Hw9gxxfHulMF5OJKCyhYD7PzlSdhzXyaGEBRPH1OPs=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=

20
main.go
View file

@ -1,11 +1,27 @@
package main
//go:generate esc -o server/assets.go -pkg server -modtime 1566640112 -ignore .DS_Store dist
import (
"embed"
"io/fs"
"github.com/andig/evcc/cmd"
"github.com/andig/evcc/server"
)
//go:embed dist
var assets embed.FS
// init loads embedded assets unless live assets are already loaded
func init() {
if server.Assets == nil {
fsys, err := fs.Sub(assets, "dist")
if err != nil {
panic(err)
}
server.Assets = fsys
}
}
func main() {
cmd.Execute()
}

File diff suppressed because it is too large Load diff

View file

@ -1,7 +0,0 @@
// +build !release
package server
const (
useLocalAssets = true
)

View file

@ -1,7 +0,0 @@
// +build release
package server
const (
useLocalAssets = false
)

View file

@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"html/template"
"io/fs"
"net/http"
"os"
"strconv"
@ -17,6 +18,9 @@ import (
"github.com/gorilla/mux"
)
// Assets is the embedded assets file system
var Assets fs.FS
type chargeModeJSON struct {
Mode api.ChargeMode `json:"mode"`
}
@ -49,17 +53,17 @@ func routeLogger(inner http.Handler) http.HandlerFunc {
}
}
func indexHandler(site core.SiteAPI, useLocal bool) http.HandlerFunc {
func indexHandler(site core.SiteAPI) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=UTF-8")
indexTemplate, err := FSString(useLocal, "/dist/index.html")
indexTemplate, err := fs.ReadFile(Assets, "index.html")
if err != nil {
log.FATAL.Print("httpd: failed to load embedded template:", err.Error())
log.FATAL.Fatal("Make sure templates are included using the `release` build tag or use `make build`")
}
t, err := template.New("evcc").Delims("[[", "]]").Parse(indexTemplate)
t, err := template.New("evcc").Delims("[[", "]]").Parse(string(indexTemplate))
if err != nil {
log.FATAL.Fatal("httpd: failed to create main page template:", err.Error())
}
@ -220,7 +224,6 @@ func MinSoCHandler(loadpoint core.LoadPointAPI) http.HandlerFunc {
}
if !ok || err != nil {
log.DEBUG.Printf("parse soc: %v", err)
w.WriteHeader(http.StatusBadRequest)
return
}
@ -338,15 +341,9 @@ func NewHTTPd(url string, site core.SiteAPI, hub *SocketHub, cache *util.Cache)
static := router.PathPrefix("/").Subrouter()
static.Use(handlers.CompressHandler)
static.HandleFunc("/", indexHandler(site, useLocalAssets))
var distDir = Dir(false, "/dist/")
if useLocalAssets {
distDir = http.Dir("./dist")
}
for _, public := range []string{"css", "js", "ico"} {
static.PathPrefix(fmt.Sprintf("/%s/", public)).Handler(
http.Handler(http.FileServer(distDir)),
)
static.HandleFunc("/", indexHandler(site))
for _, dir := range []string{"css", "js", "ico"} {
static.PathPrefix("/" + dir).Handler(http.FileServer(http.FS(Assets)))
}
// api

11
server/http_live.go Normal file
View file

@ -0,0 +1,11 @@
// +build !release
package server
import (
"os"
)
func init() {
Assets = os.DirFS("dist")
}

View file

@ -4,5 +4,4 @@ package main
import (
_ "github.com/golang/mock/mockgen"
_ "github.com/mjibson/esc"
)